android 10 , android 11 预置系统应用权限开启分析
今天遇见的问题: 预装的应用 打开之后 申请了动态权限。 客户要求默认授予 优化体验
所以 问题就变成了 系统应用的权限如何默认开启
分析
通过源码分析 在frameowork中 有专门的Grant permmsion机制
android 10
DefaultSystemDialerApp为例 观察流程
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
grantDefaultPermissions
public void grantDefaultPermissions(int userId) {
grantPermissionsToSysComponentsAndPrivApps(userId);
grantDefaultSystemHandlerPermissions(userId);
grantDefaultPermissionExceptions(userId);
synchronized (mLock) {
mDefaultPermissionsGrantedUsers.put(userId, userId);
}
}
grantDefaultSystemHandlerPermissions
private void grantDefaultSystemHandlerPermissions(int userId) {
Log.i(TAG, "Granting permissions to default platform handlers for user " + userId);
final PackagesProvider locationPackagesProvider;
final PackagesProvider locationExtraPackagesProvider;
final PackagesProvider voiceInteractionPackagesProvider;
final PackagesProvider smsAppPackagesProvider;
final PackagesProvider dialerAppPackagesProvider;
final PackagesProvider simCallManagerPackagesProvider;
final PackagesProvider useOpenWifiAppPackagesProvider;
final SyncAdapterPackagesProvider syncAdapterPackagesProvider;
synchronized (mLock) {
locationPackagesProvider = mLocationPackagesProvider;
locationExtraPackagesProvider = mLocationExtraPackagesProvider;
voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
smsAppPackagesProvider = mSmsAppPackagesProvider;
dialerAppPackagesProvider = mDialerAppPackagesProvider;
simCallManagerPackagesProvider = mSimCallManagerPackagesProvider;
useOpenWifiAppPackagesProvider = mUseOpenWifiAppPackagesProvider;
syncAdapterPackagesProvider = mSyncAdapterPackagesProvider;
}
String[] voiceInteractPackageNames = (voiceInteractionPackagesProvider != null)
? voiceInteractionPackagesProvider.getPackages(userId) : null;
String[] locationPackageNames = (locationPackagesProvider != null)
? locationPackagesProvider.getPackages(userId) : null;
String[] locationExtraPackageNames = (locationExtraPackagesProvider != null)
? locationExtraPackagesProvider.getPackages(userId) : null;
String[] smsAppPackageNames = (smsAppPackagesProvider != null)
? smsAppPackagesProvider.getPackages(userId) : null;
String[] dialerAppPackageNames = (dialerAppPackagesProvider != null)
? dialerAppPackagesProvider.getPackages(userId) : null;
String[] simCallManagerPackageNames = (simCallManagerPackagesProvider != null)
? simCallManagerPackagesProvider.getPackages(userId) : null;
String[] useOpenWifiAppPackageNames = (useOpenWifiAppPackagesProvider != null)
? useOpenWifiAppPackagesProvider.getPackages(userId) : null;
String[] contactsSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
syncAdapterPackagesProvider.getPackages(ContactsContract.AUTHORITY, userId) : null;
String[] calendarSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
// SetupWizard
grantPermissionsToSystemPackage(
getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId,
PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
CAMERA_PERMISSIONS);
// Camera
grantPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackage(MediaStore.ACTION_IMAGE_CAPTURE, userId),
userId, CAMERA_PERMISSIONS, MICROPHONE_PERMISSIONS, STORAGE_PERMISSIONS);
// Dialer
if (dialerAppPackageNames == null) {
String dialerPackage =
getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId);
grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
} else {
for (String dialerAppPackageName : dialerAppPackageNames) {
grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId);
}
}
}
grantDefaultPermissionsToDefaultSystemDialerApp
private void grantDefaultPermissionsToDefaultSystemDialerApp(
String dialerPackage, int userId) {
if (dialerPackage == null) {
return;
}
boolean isPhonePermFixed =
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
if (isPhonePermFixed) {
grantSystemFixedPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
} else {
grantPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
}
grantPermissionsToSystemPackage(dialerPackage, userId,
CONTACTS_PERMISSIONS, SMS_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
}
对于额外的预置应用 提供了如下方法
getDefaultPermissionFiles
private File[] getDefaultPermissionFiles() {
ArrayList<File> ret = new ArrayList<File>();
File dir = new File(Environment.getRootDirectory(), "etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
dir = new File(Environment.getVendorDirectory(), "etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
dir = new File(Environment.getOdmDirectory(), "etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
dir = new File(Environment.getProductDirectory(), "etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
dir = new File(Environment.getProductServicesDirectory(),
"etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
// For IoT devices, we check the oem partition for default permissions for each app.
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED, 0)) {
dir = new File(Environment.getOemDirectory(), "etc/default-permissions");
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
}
return ret.isEmpty() ? null : ret.toArray(new File[0]);
}
示例xml
makefile:
packages/services/Car/car_product/build/default-car-permissions.xml:system/etc/default-permissions/default-car-permissions.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<!--
This file contains permissions to be granted by default. Default
permissions are granted to special platform components and to apps
that are approved to get default grants. The special components
are apps that are expected tto work out-of-the-box as they provide
core use cases such as default dialer, default email, etc. These
grants are managed by the platform. The apps that are additionally
approved for default grants are ones that provide carrier specific
functionality, ones legally required at some location, ones providing
alternative disclosure and opt-out UI, ones providing highlight features
of a dedicated device, etc. This file contains only the latter exceptions.
Fixed permissions cannot be controlled by the user and need a special
approval. Typically these are to ensure either legally mandated functions
or the app is considered a part of the OS.
-->
<exceptions>
<!-- This is an example of an exception:
<exception
package="foo.bar.permission"
<permission name="android.permission.READ_CONTACTS" fixed="true"/>
<permission name="android.permission.READ_CALENDAR" fixed="false"/>
</exception>
-->
<exception
package="com.android.car.messenger">
<!-- Contacts -->
<permission name="android.permission.READ_CONTACTS" fixed="false"/>
<!-- SMS -->
<permission name="android.permission.SEND_SMS" fixed="false"/>
<permission name="android.permission.READ_SMS" fixed="false"/>
</exception>
</exceptions>
VTS 测试如下:
ValidateDefaultPermissions.cpp
TEST(CheckConfig, defaultPermissions) {
RecordProperty("description",
"Verify that the default-permissions file "
"is valid according to the schema");
std::vector<const char*> locations = {"/vendor/etc/default-permissions",
"/odm/etc/default-permissions"};
for (const char* dir_path : locations) {
std::vector<std::string> files = get_files_in_dirs(dir_path);
for (auto& file_name : files) {
EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(file_name.c_str(), {dir_path},
"/data/local/tmp/default-permissions.xsd");
}
}
总结
预置到系统的应用默认权限开启
- 可以在xml中定义格式如下
-->
<exceptions>
<!-- This is an example of an exception:
<exception
package="foo.bar.permission"
<permission name="android.permission.READ_CONTACTS" fixed="true"/>
<permission name="android.permission.READ_CALENDAR" fixed="false"/>
</exception>
-->
预置xml文件可以放置的问题
locations = {"/vendor/etc/default-permissions",
"/odm/etc/default-permissions"};
可使用的文件名参考
system/etc/default-permissions/default-car-permissions.xml