1. 首页 > 电脑知识

设置-权限PMS流程梳理 设置权限流程

作者:admin 更新时间:2025-06-29
摘要:Android M之前,权限都是在安装时授予的,虽然在4.3时,Google就尝试在源码里面引入AppOpsManager来达到动态控制权限的目的,但由于不太成熟,在Release版本并没有释放这个功能。在6.0之后,Google为了简化安装流程且方便用户控制权限,正式引入了runtime-permission,允许用户在运行的时候动态控制权限。对于开发而言,设置-权限PMS流程梳理 设置权限流程

 

Android M之前,权限都是在安装时授予的,虽然在4.3时,Google就尝试在源码里面引入AppOpsManager来达到动态控制权限的目的,但 由于不太成熟,在Release版本并没有释放这个功能。在6.0之后,Google为了简化安装流程且方便用户控制权限,正式引入了runtime-permission,允许用户在运行的时候动态控制权限。对于开发而言就是将targetSdkVersion设置为23, 并且在相应的时机动态申请权限,在适配了Android6.0的App运行在Android 6.0+的定位器上时,就会调用6.0相关的API,不过在低版本的 上,依旧是按安装时权限处理。

1. 适配Android运行时权限

适配Android Runtime Permission,常见的步骤如下:

1.1 在AndroidManifest文件中添加需要的权限。

这个步骤和我们之前的开发并没有 何变化,尝试去申请一个没有声明的权限可能会导致程序崩溃。

1.2 检查权限

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { //申请权限 }

这里涉及到一个API,ContextCompat.checkSelfPermission,主要用于检测某个权限是否已经被授予, 技巧返回值为PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。当返回DENIED就需要进行申请授权了。

1.3 申请授权

ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_CODE);

该 技巧是异步的,第一个参数是Context;第二个参数是需要申请的权限的字符串数组;第三个参数为requestCode,主要用于回调的时候检测。可以从 技巧名requestPermissions以及第二个参数看出,是支持一次性申请多个权限的, 体系会通过对话框逐一询问用户是否授权。

1.4处理权限申请回调

@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSIONS_REQUEST_CODE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //权限申请成功 } else { //权限申请失败 } return; } } }

该 技巧在权限申请之后会回调,第一验证requestCode, 接着验证grantResults对应于申请的 结局,这里的数组对应于申请时的第二个权限字符串数组。如果你同时申请两个权限,那么grantResults的length就为2,分别记录你两个权限的申请 结局。 以上的步骤对于我们Android开发者来说都很熟悉, 然而很少有人研究Android鉴权的底层逻辑,今天我们就从上述调用的api入手,来研究Android权限的调用流程。

2. 检查权限流程

检查权限通过 体系api ActivityCompat.requestPermissions()进行,其底层通过上下文对象ContextImpl调用PermissionManager.checkPermission() 技巧。 frameworks/base/core/java/android/app/ContextImpl.java

@Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } return PermissionManager.checkPermission(permission, pid, uid); }

PermissionManager 中 checkPermission()采用缓存机制,将最近检查的权限缓存起来,缓存中没有的权限,调用checkPermissionUncached() 技巧从底层服务中继续查询。 正常情况下,会拿到AMS的binder对象,调用AMS checkPermission() 技巧。 frameworks/base/core/java/android/permission/PermissionManager.java

/* @hide */ private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) { final IActivityManager am = ActivityManager.getService(); ...... try { return am.checkPermission(permission, pid, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

checkPermission() 技巧是权限检查的唯一公共入口点,在这里会将空权限字符串过滤掉。 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { return PackageManager.PERMISSION_DENIED; } return checkComponentPermission(permission, pid, uid, -1, true); }

继续执行checkComponentPermission() 技巧,这里会判断是否进程已经被拒绝访问该权限,如果是就直接返回PERMISSION_GRANTED。如果不是,就继续执行ActivityManager.checkComponentPermission() 技巧。

public static int checkComponentPermission(String permission, int pid, int uid, int owningUid, boolean exported) { if (pid == MY_PID) { return PackageManager.PERMISSION_GRANTED; } // If there is an explicit permission being checked, and this is coming from a process // that has been denied access to that permission, then just deny. Ulti tely this y // not be quite right -- it means that even if the caller would have access for another // reason (such as being the owner of the component it is trying to access), it would still // fail. This also means the system and root uids would be able to deny themselves // access to permissions, which... well okay. ¯\_(ツ)_/¯ if (permission != null) { synchronized (sActiveProcessInfoSelfLocked) { ProcessInfo procInfo = sActiveProcessInfoSelfLocked.get(pid); if (procInfo != null && procInfo.deniedPermissions != null && procInfo.deniedPermissions.contains(permission)) { return PackageManager.PERMISSION_DENIED; } } } return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported); }

这里有执行到了ActivityManager的checkComponentPermission() 技巧,在进行一些 独特进程的判断之后,最终调用到了PMS的checkUidPermission() 技巧。 frameworks/base/core/java/android/app/ActivityManager.java

/ | @hide */ @UnsupportedAppUsage public static int checkComponentPermission(String permission, int uid, int owningUid, boolean exported) { // Root, system server get to do everything. final int appId = UserHandle.getAppId(uid); if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { return PackageManager.PERMISSION_GRANTED; } // Isolated processes don t get any permissions. if (UserHandle.isIsolated(uid)) { return PackageManager.PERMISSION_DENIED; } // If there is a uid that owns whatever is being accessed, it has // blanket access to it regardless of the permissions it requires. if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) { return PackageManager.PERMISSION_GRANTED; } // If the target is not exported, then nobody else can get to it. if (!exported) { /* RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid, here); */ return PackageManager.PERMISSION_DENIED; } if (permission == null) { return PackageManager.PERMISSION_GRANTED; } try { return AppGlobals.getPackageManager() .checkUidPermission(permission, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

和其它服务一样,PackageManagerService 由于自身功能太多,将功能细分为不同的模块调用对用的工具类,权限相关的功能就由PermissionManagerService来处理。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

// NOTE: Can t remove without a jor refactor. Keep around for now. @Override public int checkUidPermission(String permName, int uid) { /// M: CTA requirement - permission control @{ CtaManagerFactory.getInstance(). keCtaManager().reportPermRequestUsage(permName, uid); //@} try { // Because this is accessed via the package nager service AIDL, // go through the permission nager service AIDL return mPermissionManagerService.checkUidPermission(permName, uid); } catch (RemoteException ignore) { } return PackageManager.PERMISSION_DENIED; }

继续来看PermissionManagerService,这里第一调用到了checkUidPermission() 技巧,进行一些异常情况的处理,列如permission name为空,userId不存在。 接着判断checkPermissionDelegate 是否为空,正常情况下这里checkPermissionDelegate 是 空,其赋值是在AMS中的。 因此会继续流转到checkUidPermissionImpl() 技巧。 frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

@Override public int checkUidPermission(String permName, int uid) { // Not using Objects.requireNonNull() here for compatibility reasons. if (permName == null) { return PackageManager.PERMISSION_DENIED; } final int userId = UserHandle.getUserId(uid); if (!mUserManagerInt.exists(userId)) { return PackageManager.PERMISSION_DENIED; } final CheckPermissionDelegate checkPermissionDelegate; synchronized (mLock) { checkPermissionDelegate = mCheckPermissionDelegate; } if (checkPermissionDelegate == null) { return checkUidPermissionImpl(permName, uid); } return checkPermissionDelegate.checkUidPermission(permName, uid, this::checkUidPermissionImpl); }

可以看到,checkUidPermissionImpl() 技巧通过uid获取了进程对应的包信息AndroidPackage,再将其传入checkUidPermissionInternal() 技巧。

private int checkUidPermissionImpl(String permName, int uid) { final AndroidPackage pkg = mPackageManagerInt.getPackage(uid); return checkUidPermissionInternal(pkg, uid, permName); }

继续看checkUidPermissionInternalf() 技巧,AndroidPackage 不为空的情况下,会继续调用checkPermissionInternal() 技巧。

/ | * Checks whether or not the given package has been granted the specified * permission. If the given package is {@code null}, we instead check the * system permissions for the given UID. * * @see SystemConfig#getSystemPermissions() */ private int checkUidPermissionInternal(@Nullable AndroidPackage pkg, int uid, @NonNull String permissionName) { if (pkg != null) { final int userId = UserHandle.getUserId(uid); return checkPermissionInternal(pkg, false, permissionName, userId); } ...... return PackageManager.PERMISSION_DENIED; }

checkPermissionInternal() 技巧获取AndroidPackage的PackageName,将其传入mPackageManagerInt.getPackageSetting() 技巧获取PackageSetting实例(PackageSetting类存储了应用的各中信息),再获取PackageSetting的PermissionsState实例(PermissionsState是PackageSetting的属性,存储应用的权限信息),再继续调用checkSinglePermissionInternal()继续判断。

private int checkPermissionInternal(@NonNull AndroidPackage pkg, boolean isPackageExplicit, @NonNull String permissionName, @UserIdInt int userId) { final int callingUid = getCallingUid(); ...... final int uid = UserHandle.getUid(userId, pkg.getUid()); final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( pkg.getPackageName()); if (ps == null) { return PackageManager.PERMISSION_DENIED; } final PermissionsState permissionsState = ps.getPermissionsState(); if (checkSinglePermissionInternal(uid, permissionsState, permissionName)) { return PackageManager.PERMISSION_GRANTED; } ....... return PackageManager.PERMISSION_DENIED; }

checkSinglePermissionInternal()很简单,调用PermissionsState.hasPermission() 技巧进行判断。

private boolean checkSinglePermissionInternal(int uid, @NonNull PermissionsState permissionsState, @NonNull String permissionName) { if (!permissionsState.hasPermission(permissionName, UserHandle.getUserId(uid))) { return false; } ...... return true; }

PermissionsState中维护了一个ArrayMap mPermissions,mPermissions存储了应用的权限数据PermissionData,通过调用permissionData.isGranted()来最终判断是否具有该项权限。 frameworks/base/services/core/java/com/android/server/pm/permission/PermissionsState.java

/ | * Gets whether the state has a given permission for the specified * user, regardless if this is an install or a runtime permission. * * @param name The permission name. * @param userId The device user id. * @return Whether the user has the permission. */ public boolean hasPermission(String name, int userId) { enforceValidUserId(userId); synchronized (mLock) { if (mPermissions == null) { return false; } PermissionData permissionData = mPermissions.get(name); return permissionData != null && permissionData.isGranted(userId); } }

以上,就是运行时权限的检查流程。

3. 申请权限流程

申请权限调用 Activity.requestPermissions(thisActivity,new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_CODE)接口,requestPermissions 技巧构造一个intent,intent指向android.content.pm.action.REQUEST_PERMISSIONS,启动权限管理器PermissionController。 frameworks/base/core/java/android/app/Activity.java

public final void requestPermissions(@NonNull String[] permissions, int requestCode) { if (requestCode < 0) { throw new IllegalArgumentException("requestCode should be >= 0"); } if (mHasCurrentPermissionsRequest) { Log.w(TAG, "Can request only one set of permissions at a time"); // Dispatch the callback with empty arrays which means a cancellation. onRequestPermissionsResult(requestCode, new String[0], new int[0]); return; } Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions); startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null); mHasCurrentPermissionsRequest = true; }

权限管理器用于权限申请的界面为GrantPermissionsActivity.java,我们省略UI上的流程,直接来到权限申请完成的逻辑,用户点击权限弹框上的选项之后,会回调onPermissionGrantResult() 技巧,对权限申请进行处理。我们看到。这里有6中 情形:

  • CANCELED:撤销权限申请
  • GRANTED_ALWAYS :任 什么时候候候都允许
  • GRANTED_FOREGROUND_ONLY :仅在使用该应用时允许
  • GRANTED_ONE_TIME:仅限这一次
  • DENIED:拒绝
  • DENIED_DO_NOT_ASK_AGAIN:拒绝并不再询问 除CANCELED没有实际操作之外,其它的选项都会调用onPermissionGrantResultSingleState这个 技巧,不同的是每种 情形传递的参数不同。 参数意义:

对于权限组,这里有两种foregroundGroupState 和 backgroundGroupState ,foregroundGroupState 代表只在允许前台访问的权限组,backgroundGroupState 代表允许后台访问的权限组。

  • groupState: 权限组的 情形,包括foregroundGroupState 和 backgroundGroupState
  • granted:是否允许权限
  • isOneTime: 是否只允许一次权限
  • doNotAskAgain: 如果权限被拒绝,是否应该再次申请

以GRANTED_FOREGROUND_ONLY 为例,它仅允许应用在使用期间访问权限, 因此foregroundGroupState granted传值为true,backgroundGroupState granted传值为false。 onPermissionGrantResultSingleState(foregroundGroupState, true, false, false); onPermissionGrantResultSingleState(backgroundGroupState, false, false, false); packages/apps/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java

@Override public void onPermissionGrantResult(String name, @GrantPermissionsViewHandler.Result int result) { GroupState foregroundGroupState = getForegroundGroupState(name); GroupState backgroundGroupState = getBackgroundGroupState(name); ...... switch (result) { case CANCELED: if (foregroundGroupState != null) { reportRequestResult(foregroundGroupState.affectedPermissions, PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED); } if (backgroundGroupState != null) { reportRequestResult(backgroundGroupState.affectedPermissions, PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED); } setResultAndFinish(); return; case GRANTED_ALWAYS : if (foregroundGroupState != null) { onPermissionGrantResultSingleState(foregroundGroupState, true, false, false); } if (backgroundGroupState != null) { onPermissionGrantResultSingleState(backgroundGroupState, true, false, false); } break; case GRANTED_FOREGROUND_ONLY : if (foregroundGroupState != null) { onPermissionGrantResultSingleState(foregroundGroupState, true, false, false); } if (backgroundGroupState != null) { onPermissionGrantResultSingleState(backgroundGroupState, false, false, false); } break; case GRANTED_ONE_TIME: if (foregroundGroupState != null) { onPermissionGrantResultSingleState(foregroundGroupState, true, true, false); } if (backgroundGroupState != null) { onPermissionGrantResultSingleState(backgroundGroupState, false, true, false); } break; case DENIED : if (foregroundGroupState != null) { onPermissionGrantResultSingleState(foregroundGroupState, false, false, false); } if (backgroundGroupState != null) { onPermissionGrantResultSingleState(backgroundGroupState, false, false, false); } break; case DENIED_DO_NOT_ASK_AGAIN : if (foregroundGroupState != null) { onPermissionGrantResultSingleState(foregroundGroupState, false, false, true); } if (backgroundGroupState != null) { onPermissionGrantResultSingleState(backgroundGroupState, false, false, true); } break; } if (!showNextPermissionGroupGrantRequest()) { setResultAndFinish(); } }

我们继续来看onPermissionGrantResultSingleState() 技巧,它对我们传递进来的参数进行处理。 如果granted为true,执行权限组的groupState.mGroup.grantRuntimePermissions() 技巧; 如果granted为false,执行权限组的groupState.mGroup.revokeRuntimePermissions() 技巧;

private void onPermissionGrantResultSingleState(GroupState groupState, boolean granted, boolean isOneTime, boolean doNotAskAgain) { if (groupState != null && groupState.mGroup != null && groupState.mState == GroupState.STATE_UNKNOWN) { if (granted) { int permissionGrantRequestResult = PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED; if (isOneTime) { groupState.mGroup.setOneTime(true); permissionGrantRequestResult = PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_ONE_TIME; } else { groupState.mGroup.setOneTime(false); } groupState.mGroup.grantRuntimePermissions(true, doNotAskAgain, groupState.affectedPermissions); groupState.mState = GroupState.STATE_ALLOWED; reportRequestResult(groupState.affectedPermissions, permissionGrantRequestResult); } else { groupState.mGroup.revokeRuntimePermissions(doNotAskAgain, groupState.affectedPermissions); groupState.mGroup.setOneTime(false); groupState.mState = GroupState.STATE_DENIED; reportRequestResult(groupState.affectedPermissions, doNotAskAgain ?PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE : PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED); } } }

我们继续来看AppPermissionGroup grantRuntimePermissions() 技巧, 技巧很长,我们逐一来分析。

  • 第一,这里for循环将遍历权限组的所有权限,filterPermissions如果为空,则遍历所有权限,filterPermissions如果不为空,则只遍历filterPermissions中的权限。
  • 如果不支持运行时权限(权限非运行时权限或SDK<23),则不处理
  • 如果是 体系设置的权限,不进行处理
  • 在授予权限前,请确认权限应用可操作性已开启。
  • 权限granted设置为true
  • 更新权限的标记 权限更改完成之后,这里只是将数据保存在了permissionController,并没有持久化,还需要调用persistChanges() 技巧持久化数据。 packages/apps/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
  • public boolean grantRuntimePermissions(boolean setByTheUser, boolean fixedByTheUser, String[] filterPermissions) { boolean killApp = false; boolean wasAllGranted = true; // We toggle permissions only to apps that support runtime // permissions, otherwise we toggle the app op corresponding // to the permission if the permission is granted to the app. for (Permission permission : mPermissions.values()) { if (filterPermissions != null && !ArrayUtils.contains(filterPermissions, permission.getName())) { continue; } if (!permission.isGrantingAllowed(mIsEphemeralApp, mAppSupportsRuntimePermissions)) { // Skip unallowed permissions. continue; } boolean wasGranted = permission.isGrantedIncludingAppOp(); if (mAppSupportsRuntimePermissions) { // Do not touch permissions fixed by the system. if (permission.isSystemFixed()) { wasAllGranted = false; break; } // Ensure the permission app op is enabled before the permission grant. if (permission.affectsAppOp() && !permission.isAppOpAllowed()) { permission.setAppOpAllowed(true); } // Grant the permission if needed. if (!permission.isGranted()) { permission.setGranted(true); } // Update the permission flags. if (!fixedByTheUser) { if (permission.isUserFixed()) { permission.setUserFixed(false); } if (setByTheUser) { if (!permission.isUserSet()) { permission.setUserSet(true); } } } else { if (!permission.isUserFixed()) { permission.setUserFixed(true); } if (permission.isUserSet()) { permission.setUserSet(false); } } } ...... } if (!mDelayChanges) { persistChanges(false); if (killApp) { killApp(KILL_REASON_APP_OP_CHANGE); } } return wasAllGranted; }

    我们继续看persistChanges() 技巧,这里会遍历mPermissions,判断权限是否授予,如果没有授予就调用PKMS grantRuntimePermission() 技巧授权,如果已经授权了,就调用revokeRuntimePermission() 技巧撤销权限。

    / | * If the changes to this group were delayed, persist them to the platform. * * @param yKillBecauseOfAppOpsChange If the app these permissions belong to y be killed if * app ops change. If this is set to {@code false} the * caller has to ke sure to kill the app if needed. * @param revokeReason If any permissions are getting revoked, the reason for revoking them. */ public void persistChanges(boolean yKillBecauseOfAppOpsChange, String revokeReason) { int uid = mPackageInfo.applicationInfo.uid; int numPermissions = mPermissions.size(); boolean shouldKillApp = false; for (int i = 0; i < numPermissions; i++) { Permission permission = mPermissions.valueAt(i); if (!permission.isSystemFixed()) { if (permission.isGranted()) { mPackageManager.grantRuntimePermission(mPackageInfo.packageName, permission.getName(), mUserHandle); } else { boolean isCurrentlyGranted = mContext.checkPermission(permission.getName(), -1, uid) == PERMISSION_GRANTED; if (isCurrentlyGranted) { if (revokeReason == null) { mPackageManager.revokeRuntimePermission(mPackageInfo.packageName, permission.getName(), mUserHandle); } else { mPackageManager.revokeRuntimePermission(mPackageInfo.packageName, permission.getName(), mUserHandle, revokeReason); } } } } ...... }

    和检查权限一样,PackageManagerService并不处理权限相关的逻辑,而是将它交给PermissionManagerService处理。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

    // NOTE: Can t remove due to unsupported app usage @Override public void grantRuntimePermission(String packageName, String permName, final int userId) { try { // Because this is accessed via the package nager service AIDL, // go through the permission nager service AIDL mPermissionManagerService.grantRuntimePermission(packageName, permName, userId); } catch (RemoteException ignore) { } }

    PermissionManagerService grantRuntimePermission() 技巧调用grantRuntimePermissionInternal() 技巧继续处理,我们省略前面的一系列合法性判断,只看关键步骤。这里和checkPermissionInternal()一样,通过AndroidPackage 获取PackageSetting,再通过PackageSetting获取permissionsState 实例,最终通过permissionsState 的 grantRuntimePermission()来完成授权。 frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

    @Override public void grantRuntimePermission(String packageName, String permName, final int userId) { final int callingUid = Binder.getCallingUid(); final boolean overridePolicy = checkUidPermission(ADJUST_RUNTIME_PERMISSIONS_POLICY, callingUid) == PackageManager.PERMISSION_GRANTED; grantRuntimePermissionInternal(permName, packageName, overridePolicy, callingUid, userId, mDefaultPermissionCallback); } // TODO swap permission name and package name private void grantRuntimePermissionInternal(String permName, String packageName, boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) { ...... final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( packageName); ...... final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid())); final PermissionsState permissionsState = ps.getPermissionsState(); ...... final int result = permissionsState.grantRuntimePermission(bp, userId); switch (result) { case PERMISSION_OPERATION_FAILURE: { return; } case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: { if (callback != null) { callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId); } } break; } ...... }

    我们之前了解过,PermissionsState中维护了一个ArrayMap mPermissions,mPermissions存储了应用的权限数据PermissionData,最终通过调用permissionData.grant()来将授权数据持久化到平台。 frameworks/base/services/core/java/com/android/server/pm/permission/PermissionsState.java

    public int grantRuntimePermission(BasePermission permission, int userId) { enforceValidUserId(userId); if (userId == UserHandle.USER_ALL) { return PERMISSION_OPERATION_FAILURE; } return grantPermission(permission, userId); }

    private int grantPermission(BasePermission permission, int userId) { if (hasPermission(permission.getName(), userId)) { return PERMISSION_OPERATION_SUCCESS; } final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId)); final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS; PermissionData permissionData = ensurePermissionData(permission); if (!permissionData.grant(userId)) { return PERMISSION_OPERATION_FAILURE; } if (hasGids) { final int[] newGids = computeGids(userId); if (oldGids.length != newGids.length) { return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; } } return PERMISSION_OPERATION_SUCCESS; }

    应用的授权 经过就解析完毕。