赞
踩
Android开机后,除了根据上次开机的记录(runtime-permissions.xml)授予运行时权限外,一些系统重要的组件也需要提前授予运行时权限,最常见的时为系统重要功能的默认组件提前授予运行时权限,例如系统会为默认的浏览器提前授予位置相关的运行时权限。而这些授权操作,是在DefaultPermissionGrantPolicy类里面进行的。DefaultPermissionGrantPolicy在PermissionManagerService的构造函数中被创建。
默认应用的设置可以在设置-应用和通知-默认应用中找到。
frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
PermissionManagerService(Context context,
@NonNull Object externalLock) {
...
mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
context, mHandlerThread.getLooper(), this);
在PMS的systemReady阶段中,会调用DefaultPermissionGrantPolicy#grantDefaultPermissions为每一个修改过运行时权限的userid提前授予运行时权限(创建新用户也会触发授权,此处略过):
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override
public void systemReady() {
...
// If we upgraded grant all default permissions before kicking off.
for (int userId : grantPermissionsUserIds) {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
}
提前授权的步骤分三步:1.系统特权组件授权;2.系统默认组件授权;3.特定文件指定授权。
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
public void grantDefaultPermissions(int userId) {
grantPermissionsToSysComponentsAndPrivApps(userId);
grantDefaultSystemHandlerPermissions(userId);
grantDefaultPermissionExceptions(userId);
synchronized (mLock) {
mDefaultPermissionsGrantedUsers.put(userId, userId);
}
}
首先列出主用户下所有已安装的包,过滤掉以下包:1.不支持运行时权限的(targetsdk小于M);2.没有声明申请权限的;3.不属于特权apk的;4.如果是属于更新过后的系统应用,原来的系统应用不是persistent的;5.如果不属于更新过后的系统应用,此应用不是persistent的;
6.没有系统(platform)签名的。其他包和UID小于10000(应用程序的首个UID)的包会被授予运行时权限。
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private void grantPermissionsToSysComponentsAndPrivApps(int userId) { Log.i(TAG, "Granting permissions to platform components for user " + userId); List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser( DEFAULT_PACKAGE_INFO_QUERY_FLAGS, UserHandle.USER_SYSTEM); for (PackageInfo pkg : packages) { if (pkg == null) { continue; } if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg) || !doesPackageSupportRuntimePermissions(pkg) || ArrayUtils.isEmpty(pkg.requestedPermissions)) { continue; } grantRuntimePermissionsForSystemPackage(userId, pkg); } }
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageInfo pkg) { if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) { return true; } if (!pkg.applicationInfo.isPrivilegedApp()) { return false; } final PackageInfo disabledPkg = getSystemPackageInfo( mServiceInternal.getDisabledSystemPackageName(pkg.applicationInfo.packageName)); if (disabledPkg != null) { ApplicationInfo disabledPackageAppInfo = disabledPkg.applicationInfo; if (disabledPackageAppInfo != null && (disabledPackageAppInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) { return false; } } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) { return false; } return mServiceInternal.isPlatformSigned(pkg.packageName); }
对于这部分符合要求的系统组件,系统的策略是尽可能授予组件需要的任何运行时权限。
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private void grantRuntimePermissionsForSystemPackage(int userId, PackageInfo pkg) {
Set<String> permissions = new ArraySet<>();
for (String permission : pkg.requestedPermissions) {
final BasePermission bp = mPermissionManager.getPermission(permission);
if (bp == null) {
continue;
}
if (bp.isRuntime()) {
permissions.add(permission);
}
}
if (!permissions.isEmpty()) {
grantRuntimePermissions(pkg, permissions, true /*systemFixed*/, userId);
}
}
系统需要相应一部分重要的intent的默认包被授予特定的运行时权限,所以就通过grantDefaultSystemHandlerPermissions为这些包授予特定的运行时权限。
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
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; // Installer grantSystemFixedPermissionsToSystemPackage( ArrayUtils.firstOrNull(getKnownPackages( PackageManagerInternal.PACKAGE_INSTALLER, userId)), userId, STORAGE_PERMISSIONS); // Verifier final String verifier = ArrayUtils.firstOrNull(getKnownPackages( PackageManagerInternal.PACKAGE_VERIFIER, userId)); grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS); grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS); // SetupWizard grantPermissionsToSystemPackage( ArrayUtils.firstOrNull(getKnownPackages( 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); // Sound recorder grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( MediaStore.Audio.Media.RECORD_SOUND_ACTION, userId), userId, MICROPHONE_PERMISSIONS); // Media provider grantSystemFixedPermissionsToSystemPackage( getDefaultProviderAuthorityPackage(MediaStore.AUTHORITY, userId), userId, STORAGE_PERMISSIONS, PHONE_PERMISSIONS); // Downloads provider grantSystemFixedPermissionsToSystemPackage( getDefaultProviderAuthorityPackage("downloads", userId), userId, STORAGE_PERMISSIONS); // Downloads UI grantSystemFixedPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( DownloadManager.ACTION_VIEW_DOWNLOADS, userId), userId, STORAGE_PERMISSIONS); // Storage provider grantSystemFixedPermissionsToSystemPackage( getDefaultProviderAuthorityPackage("com.android.externalstorage.documents", userId), userId, STORAGE_PERMISSIONS); // CertInstaller grantSystemFixedPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage(Credentials.INSTALL_ACTION, userId), userId, STORAGE_PERMISSIONS); // Dialer if (dialerAppPackageNames == null) { String dialerPackage = getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId); grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId); } else { for (String dialerAppPackageName : dialerAppPackageNames) { grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId); } } // Sim call manager if (simCallManagerPackageNames != null) { for (String simCallManagerPackageName : simCallManagerPackageNames) { grantDefaultPermissionsToDefaultSystemSimCallManager( simCallManagerPackageName, userId); } } // Use Open Wifi if (useOpenWifiAppPackageNames != null) { for (String useOpenWifiPackageName : useOpenWifiAppPackageNames) { grantDefaultPermissionsToDefaultSystemUseOpenWifiApp( useOpenWifiPackageName, userId); } } // SMS if (smsAppPackageNames == null) { String smsPackage = getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_MESSAGING, userId); grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId); } else { for (String smsPackage : smsAppPackageNames) { grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId); } } // Cell Broadcast Receiver grantSystemFixedPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage(Intents.SMS_CB_RECEIVED_ACTION, userId), userId, SMS_PERMISSIONS); // Carrier Provisioning Service grantPermissionsToSystemPackage( getDefaultSystemHandlerServicePackage(Intents.SMS_CARRIER_PROVISION_ACTION, userId), userId, SMS_PERMISSIONS); // Calendar grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_CALENDAR, userId), userId, CALENDAR_PERMISSIONS, CONTACTS_PERMISSIONS); // Calendar provider String calendarProvider = getDefaultProviderAuthorityPackage(CalendarContract.AUTHORITY, userId); grantPermissionsToSystemPackage(calendarProvider, userId, CONTACTS_PERMISSIONS, STORAGE_PERMISSIONS); grantSystemFixedPermissionsToSystemPackage(calendarProvider, userId, CALENDAR_PERMISSIONS); // Calendar provider sync adapters grantPermissionToEachSystemPackage( getHeadlessSyncAdapterPackages(calendarSyncAdapterPackages, userId), userId, CALENDAR_PERMISSIONS); // Contacts grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_CONTACTS, userId), userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS); // Contacts provider sync adapters grantPermissionToEachSystemPackage( getHeadlessSyncAdapterPackages(contactsSyncAdapterPackages, userId), userId, CONTACTS_PERMISSIONS); // Contacts provider String contactsProviderPackage = getDefaultProviderAuthorityPackage(ContactsContract.AUTHORITY, userId); grantSystemFixedPermissionsToSystemPackage(contactsProviderPackage, userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS); grantPermissionsToSystemPackage(contactsProviderPackage, userId, STORAGE_PERMISSIONS); // Device provisioning grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId), userId, CONTACTS_PERMISSIONS); // Maps grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId), userId, ALWAYS_LOCATION_PERMISSIONS); // Gallery grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_GALLERY, userId), userId, STORAGE_PERMISSIONS); // Email grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_EMAIL, userId), userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS); // Browser String browserPackage = ArrayUtils.firstOrNull(getKnownPackages( PackageManagerInternal.PACKAGE_BROWSER, userId)); if (browserPackage == null) { browserPackage = getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_APP_BROWSER, userId); if (!isSystemPackage(browserPackage)) { browserPackage = null; } } grantPermissionsToPackage(browserPackage, userId, false /* ignoreSystemPackage */, true /*whitelistRestrictedPermissions*/, ALWAYS_LOCATION_PERMISSIONS); // Voice interaction if (voiceInteractPackageNames != null) { for (String voiceInteractPackageName : voiceInteractPackageNames) { grantPermissionsToSystemPackage(voiceInteractPackageName, userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS, PHONE_PERMISSIONS, SMS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS); } } if (ActivityManager.isLowRamDeviceStatic()) { // Allow voice search on low-ram devices grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId), userId, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS); } // Voice recognition Intent voiceRecoIntent = new Intent(RecognitionService.SERVICE_INTERFACE) .addCategory(Intent.CATEGORY_DEFAULT); grantPermissionsToSystemPackage( getDefaultSystemHandlerServicePackage(voiceRecoIntent, userId), userId, MICROPHONE_PERMISSIONS); // Location if (locationPackageNames != null) { for (String packageName : locationPackageNames) { grantPermissionsToSystemPackage(packageName, userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS, PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS, SENSORS_PERMISSIONS, STORAGE_PERMISSIONS); grantSystemFixedPermissionsToSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS); } } if (locationExtraPackageNames != null) { // Also grant location permission to location extra packages. for (String packageName : locationExtraPackageNames) { grantPermissionsToSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS); } } // Music Intent musicIntent = new Intent(Intent.ACTION_VIEW) .addCategory(Intent.CATEGORY_DEFAULT) .setDataAndType(Uri.fromFile(new File("foo.mp3")), AUDIO_MIME_TYPE); grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage(musicIntent, userId), userId, STORAGE_PERMISSIONS); // Home Intent homeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) .addCategory(Intent.CATEGORY_LAUNCHER_APP); grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage(homeIntent, userId), userId, ALWAYS_LOCATION_PERMISSIONS); // Watches if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) { // Home application on watches String wearPackage = getDefaultSystemHandlerActivityPackageForCategory( Intent.CATEGORY_HOME_MAIN, userId); grantPermissionsToSystemPackage(wearPackage, userId, CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS); grantSystemFixedPermissionsToSystemPackage(wearPackage, userId, PHONE_PERMISSIONS); // Fitness tracking on watches grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage(ACTION_TRACK, userId), userId, SENSORS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS); } // Print Spooler grantSystemFixedPermissionsToSystemPackage(PrintManager.PRINT_SPOOLER_PACKAGE_NAME, userId, ALWAYS_LOCATION_PERMISSIONS); // EmergencyInfo grantSystemFixedPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId), userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS); // NFC Tag viewer Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW) .setType("vnd.android.cursor.item/ndef_msg"); grantPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage(nfcTagIntent, userId), userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS); // Storage Manager grantSystemFixedPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( StorageManager.ACTION_MANAGE_STORAGE, userId), userId, STORAGE_PERMISSIONS); // Companion devices grantSystemFixedPermissionsToSystemPackage( CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, userId, ALWAYS_LOCATION_PERMISSIONS); // Ringtone Picker grantSystemFixedPermissionsToSystemPackage( getDefaultSystemHandlerActivityPackage( RingtoneManager.ACTION_RINGTONE_PICKER, userId), userId, STORAGE_PERMISSIONS); // TextClassifier Service String textClassifierPackageName = mContext.getPackageManager().getSystemTextClassifierPackageName(); if (!TextUtils.isEmpty(textClassifierPackageName)) { grantPermissionsToSystemPackage(textClassifierPackageName, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS, CALENDAR_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS); } // Atthention Service String attentionServicePackageName = mContext.getPackageManager().getAttentionServicePackageName(); if (!TextUtils.isEmpty(attentionServicePackageName)) { grantPermissionsToSystemPackage(attentionServicePackageName, userId, CAMERA_PERMISSIONS); } // There is no real "marker" interface to identify the shared storage backup, it is // hardcoded in BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE. grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId, STORAGE_PERMISSIONS); // System Captions Service String systemCaptionsServicePackageName = mContext.getPackageManager().getSystemCaptionsServicePackageName(); if (!TextUtils.isEmpty(systemCaptionsServicePackageName)) { grantPermissionsToSystemPackage(systemCaptionsServicePackageName, userId, MICROPHONE_PERMISSIONS); }
系统中{partition}/etc/default-permissions目录下的xml文件可以为特定包提前授予运行时权限。
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private void grantDefaultPermissionExceptions(int userId) { mHandler.removeMessages(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS); synchronized (mLock) { // mGrantExceptions is null only before the first read and then // it serves as a cache of the default grants that should be // performed for every user. If there is an entry then the app // is on the system image and supports runtime permissions. if (mGrantExceptions == null) { mGrantExceptions = readDefaultPermissionExceptionsLocked(); } } Set<String> permissions = null; final int exceptionCount = mGrantExceptions.size(); for (int i = 0; i < exceptionCount; i++) { String packageName = mGrantExceptions.keyAt(i); PackageInfo pkg = getSystemPackageInfo(packageName); List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i); final int permissionGrantCount = permissionGrants.size(); for (int j = 0; j < permissionGrantCount; j++) { DefaultPermissionGrant permissionGrant = permissionGrants.get(j); if (!isPermissionDangerous(permissionGrant.name)) { Log.w(TAG, "Ignoring permission " + permissionGrant.name + " which isn't dangerous"); continue; } if (permissions == null) { permissions = new ArraySet<>(); } else { permissions.clear(); } permissions.add(permissionGrant.name); grantRuntimePermissions(pkg, permissions, permissionGrant.fixed, permissionGrant.whitelisted, true /*whitelistRestrictedPermissions*/, userId); } } }
`以下是其中一个xml default-permissions-google.xml的内容。package表示要额外处理的包名,sha256-cert-digest目前还没用上,permission 的name是要提前授予的权限名称,permission的fixed表示授权后是否可以被非系统组件修改权限,permission还有个whitelisted,表示是否可以为限制权限添加限制免除标志位。
<exceptions> <exception package="com.google.android.apps.restore" sha256-cert-digest="56:BE:13:2B:78:06:56:FE:24:44:CD:34:32:6E:B5:D7:AA:C9:1D:20:96:AB:F0:FE:67:3A:99:27:06:22:EC:87"> <!-- External storage --> <permission name="android.permission.READ_EXTERNAL_STORAGE" fixed="false"/> <permission name="android.permission.WRITE_EXTERNAL_STORAGE" fixed="false"/> <!-- Contacts --> <permission name="android.permission.READ_CONTACTS" fixed="false"/> <permission name="android.permission.WRITE_CONTACTS" fixed="false"/> </exception> <exception package="com.google.android.apps.assistant" sha256-cert-digest="43:0B:20:EB:61:96:7E:9C:5B:BE:02:59:9B:07:35:16:80:7D:AE:72:D7:86:FE:92:7F:48:96:B7:C7:F2:96:1F"> <!-- Record audio --> <permission name="android.permission.RECORD_AUDIO" fixed="false"/> </exception> <exception package="com.google.android.projection.gearhead" sha256-cert-digest="FD:B0:0C:43:DB:DE:8B:51:CB:31:2A:A8:1D:3B:5F:A1:77:13:AD:B9:4B:28:F5:98:D7:7F:8E:B8:9D:AC:EE:DF"> <permission name="android.permission.ACCESS_FINE_LOCATION" fixed="false"/> <permission name="android.permission.CALL_PHONE" fixed="false"/> <permission name="android.permission.READ_CALL_LOG" fixed="false"/> <permission name="android.permission.READ_CONTACTS" fixed="false"/> <permission name="android.permission.READ_PHONE_STATE" fixed="false"/> <permission name="android.permission.RECEIVE_SMS" fixed="false"/> <permission name="android.permission.RECORD_AUDIO" fixed="false"/> <permission name="android.permission.SEND_SMS" fixed="false"/> <permission name="android.permission.PROCESS_OUTGOING_CALLS" fixed="false"/> <permission name="android.permission.READ_SMS" fixed="false"/> <permission name="android.permission.RECEIVE_MMS" fixed="false"/> <permission name="android.permission.WRITE_CALL_LOG" fixed="false"/> <permission name="android.permission.ACCESS_COARSE_LOCATION" fixed="false"/> </exception> </exceptions>
无论是grantPermissionsToSystemPackage还是grantSystemFixedPermissionsToSystemPackage,还是grantPermissionsToSystemPackage。它们最终都会调用到grantRuntimePermissions,只是入参的值不一样而已。
第一个参数pkg是包的信息封装PackageInfo对象,第二个参数permissionsWithoutSplits是未被分割(split permission)的要被授予的运行时权限,第三个参数systemFixed表示本次授予的权限是否带上系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位,以免被非系统组件修改,第四个参数ignoreSystemPackage表示授权时是否考虑放置在system分区下的原应用,第五个参数whitelistRestrictedPermissions表示是否为限制权限添加限制免除(FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT)标志位,第六个参数是要授予的运行时权限对应的userid。
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage, boolean whitelistRestrictedPermissions, int userId) { UserHandle user = UserHandle.of(userId); if (pkg == null) { return; } String[] requestedPermissions = pkg.requestedPermissions; if (ArrayUtils.isEmpty(requestedPermissions)) { return; } // Intersect the requestedPermissions for a factory image with that of its current update // in case the latter one removed a <uses-permission> String[] requestedByNonSystemPackage = getPackageInfo(pkg.packageName).requestedPermissions; int size = requestedPermissions.length; for (int i = 0; i < size; i++) { if (!ArrayUtils.contains(requestedByNonSystemPackage, requestedPermissions[i])) { requestedPermissions[i] = null; } } requestedPermissions = ArrayUtils.filterNotNull(requestedPermissions, String[]::new); PackageManager pm; try { pm = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user).getPackageManager(); } catch (NameNotFoundException doesNotHappen) { throw new IllegalStateException(doesNotHappen); } final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits); ApplicationInfo applicationInfo = pkg.applicationInfo; //添加默认授权(FLAG_PERMISSION_GRANTED_BY_DEFAULT)标志位 int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; if (systemFixed) { //添加系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位 newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; } // Automatically attempt to grant split permissions to older APKs //如果要授予的权限含有split permission,把对应的new permission也加入到授权集合中 final List<PermissionManager.SplitPermissionInfo> splitPermissions = mContext.getSystemService(PermissionManager.class).getSplitPermissions(); final int numSplitPerms = splitPermissions.size(); for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) { final PermissionManager.SplitPermissionInfo splitPerm = splitPermissions.get(splitPermNum); if (applicationInfo != null && applicationInfo.targetSdkVersion < splitPerm.getTargetSdk() && permissionsWithoutSplits.contains(splitPerm.getSplitPermission())) { permissions.addAll(splitPerm.getNewPermissions()); } } Set<String> grantablePermissions = null; // In some cases, like for the Phone or SMS app, we grant permissions regardless // of if the version on the system image declares the permission as used since // selecting the app as the default for that function the user makes a deliberate // choice to grant this app the permissions needed to function. For all other // apps, (default grants on first boot and user creation) we don't grant default // permissions if the version on the system image does not declare them. //入参ignoreSystemPackage为false且目标包是更新过的system app的时候,则按system下面的包声明申请的权限为标准进行筛选 if (!ignoreSystemPackage && applicationInfo != null && applicationInfo.isUpdatedSystemApp()) { final PackageInfo disabledPkg = getSystemPackageInfo( mServiceInternal.getDisabledSystemPackageName(pkg.packageName)); if (disabledPkg != null) { if (ArrayUtils.isEmpty(disabledPkg.requestedPermissions)) { return; } if (!Arrays.equals(requestedPermissions, disabledPkg.requestedPermissions)) { grantablePermissions = new ArraySet<>(Arrays.asList(requestedPermissions)); requestedPermissions = disabledPkg.requestedPermissions; } } } final int numRequestedPermissions = requestedPermissions.length; // Sort requested permissions so that all permissions that are a foreground permission (i.e. // permissions that have a background permission) are before their background permissions. final String[] sortedRequestedPermissions = new String[numRequestedPermissions]; int numForeground = 0; int numOther = 0; for (int i = 0; i < numRequestedPermissions; i++) { String permission = requestedPermissions[i]; if (getBackgroundPermission(permission) != null) { sortedRequestedPermissions[numForeground] = permission; numForeground++; } else { sortedRequestedPermissions[numRequestedPermissions - 1 - numOther] = permission; numOther++; } } for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions; requestedPermissionNum++) { //如果是入参pkg是更新过的包且入参ignoreSystemPackage为false,这里遍历的是对应的system分区的声明申请权限;否则遍历的是目标包的声明申请权限 String permission = requestedPermissions[requestedPermissionNum]; // If there is a disabled system app it may request a permission the updated // version ot the data partition doesn't, In this case skip the permission. //如果存在更新包对应在system分区的包,system分区的包声明了某个权限,但是更新的data分区的包没有声明这个权限,则忽略这个权限 if (grantablePermissions != null && !grantablePermissions.contains(permission)) { continue; } if (permissions.contains(permission)) {//如果包声明申请的权限在本次调用所要申请的权限集合中 final int flags = mContext.getPackageManager().getPermissionFlags( permission, pkg.packageName, user); // If we are trying to grant as system fixed and already system fixed // then the system can change the system fixed grant state. final boolean changingGrantForSystemFixed = systemFixed && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0; // Certain flags imply that the permission's current state by the system or // device/profile owner or the user. In these cases we do not want to clobber the // current state. // // Unless the caller wants to override user choices. The override is // to make sure we can grant the needed permission to the default // sms and phone apps after the user chooses this in the UI. //如果1.权限不是用户设置或者固定的 2.入参ignoreSystemPackage 为false 3,尝试改变带有系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位的权限状态 三个条件满足之一 if (!isFixedOrUserSet(flags) || ignoreSystemPackage || changingGrantForSystemFixed) { // Never clobber policy fixed permissions. // We must allow the grant of a system-fixed permission because // system-fixed is sticky, but the permission itself may be revoked. //如果权限带有devicepolicy固定(FLAG_PERMISSION_POLICY_FIXED)标志位,跳过该权限 if ((flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) { continue; } // Preserve whitelisting flags. //保留所有的限制免除标志位 newFlags |= (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT); // If we are whitelisting the permission, update the exempt flag before grant. //如果入参whitelistRestrictedPermissions为true,目标权限是限制权限,为该权限添加系统限制免除(FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT)标志位 if (whitelistRestrictedPermissions && isPermissionRestricted(permission)) { mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName, PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user); } // If the system tries to change a system fixed permission from one fixed // state to another we need to drop the fixed flag to allow the grant. //如果尝试为一个带系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位的权限添加系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位,先把原来的系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位移除掉 if (changingGrantForSystemFixed) { mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName, flags, flags & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, user); } if (pm.checkPermission(permission, pkg.packageName) != PackageManager.PERMISSION_GRANTED) {//授予权限 mContext.getPackageManager() .grantRuntimePermission(pkg.packageName, permission, user); } //更新权限标志位 mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName, newFlags, newFlags, user); int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.applicationInfo.uid)); //如果目标权限是一个后台权限,遍历其对应的所有前台权限,如果对于目标包某个前台权限是授权了的,那么目标包的uid进行前台权限操作将通过appops设置成允许 List<String> fgPerms = mPermissionManager.getBackgroundPermissions() .get(permission); if (fgPerms != null) { int numFgPerms = fgPerms.size(); for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) { String fgPerm = fgPerms.get(fgPermNum); if (pm.checkPermission(fgPerm, pkg.packageName) == PackageManager.PERMISSION_GRANTED) { // Upgrade the app-op state of the fg permission to allow bg access // TODO: Dont' call app ops from package manager code. mContext.getSystemService(AppOpsManager.class).setUidMode( AppOpsManager.permissionToOp(fgPerm), uid, AppOpsManager.MODE_ALLOWED); break; } } } String bgPerm = getBackgroundPermission(permission); String op = AppOpsManager.permissionToOp(permission); if (bgPerm == null) {//如果目标权限没有对应的后台权限,直接将权限操作通过appops设置为允许 if (op != null) { // TODO: Dont' call app ops from package manager code. mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid, AppOpsManager.MODE_ALLOWED); } } else {//如果目标权限有对应的后台权限,检查对应的后台权限是否授予给目标包了,有的话将权限操作通过appops设置为允许,没有的话将权限操作通过appops设置为前台允许 int mode; if (pm.checkPermission(bgPerm, pkg.packageName) == PackageManager.PERMISSION_GRANTED) { mode = AppOpsManager.MODE_ALLOWED; } else { mode = AppOpsManager.MODE_FOREGROUND; } mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid, mode); } if (DEBUG) { Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ") + permission + " to default handler " + pkg); int appOp = AppOpsManager.permissionToOpCode(permission); if (appOp != AppOpsManager.OP_NONE && AppOpsManager.opToDefaultMode(appOp) != AppOpsManager.MODE_ALLOWED) { // Permission has a corresponding appop which is not allowed by default // We must allow it as well, as it's usually checked alongside the // permission if (DEBUG) { Log.i(TAG, "Granting OP_" + AppOpsManager.opToName(appOp) + " to " + pkg.packageName); } mContext.getSystemService(AppOpsManager.class).setUidMode( appOp, pkg.applicationInfo.uid, AppOpsManager.MODE_ALLOWED); } } } // If a component gets a permission for being the default handler A // and also default handler B, we grant the weaker grant form. if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0 && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 && !systemFixed) { if (DEBUG) { Log.i(TAG, "Granted not fixed " + permission + " to default handler " + pkg); } mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName, PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, user); } } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。