做app开发经常需求请求动态权限,比方WRITE_EXTERNAL_STORAGEACCESS_FINE_LOCATION,那么今天就从源码剖析,动态权限到底是怎样个流程,Android体系是怎样维护各个app的权限状况的,基于Android 10。对源码敏感的同学能够直接拉到底部看总结

查看权限

首要权限请求进口位于frameworks/base/core/java/android/content/Context.java

public abstract class Context {
    //省掉部分代码
	/**
     * Determine whether <em>you</em> have been granted a particular permission.
     *
     * @param permission The name of the permission being checked.
     *
     * @return {@link PackageManager#PERMISSION_GRANTED} if you have the
     * permission, or {@link PackageManager#PERMISSION_DENIED} if not.
     *
     * @see PackageManager#checkPermission(String, String)
     * @see #checkCallingPermission(String)
     */
    @PackageManager.PermissionResult
    public abstract int checkSelfPermission(@NonNull String permission);
    //省掉部分代码
}

checkSelfPermission()是一个抽象办法,办法完成在Context的子类frameworks/base/core/java/android/app/ContextImpl.java傍边

/**
 * Common implementation of Context API, which provides the base
 * context object for Activity and other application components.
 */
class ContextImpl extends Context {
    //省掉部分代码
	@Override
    public int checkSelfPermission(String permission) {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }
        return checkPermission(permission, Process.myPid(), Process.myUid());
    }
    @Override
    public int checkPermission(String permission, int pid, int uid) {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }
        //获取ActivityManagerService署理方针
        final IActivityManager am = ActivityManager.getService();
        if (am == null) {
            // Well this is super awkward; we somehow don't have an active
            // ActivityManager instance. If we're testing a root or system
            // UID, then they totally have whatever permission this is.
            final int appId = UserHandle.getAppId(uid);
            //假如是root用户或者是体系使用,直接回来已授权状况
            if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
                Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
                return PackageManager.PERMISSION_GRANTED;
            }
            Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
                    + permission);
            return PackageManager.PERMISSION_DENIED;
        }
        try {
            //经过ActivityManagerService来查看权限
            return am.checkPermission(permission, pid, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    //省掉部分代码
}

ContextImpl经过frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java来查看权限

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    //省掉部分代码
	@Override
    public int checkPermission(String permission, int pid, int uid) {
        if (permission == null) {
            return PackageManager.PERMISSION_DENIED;
        }
        //注意,参数4传的-1,参数5传的true
        return checkComponentPermission(permission, pid, uid, -1, true);
    }
    public static int checkComponentPermission(String permission, int pid, int uid,
            int owningUid, boolean exported) {
        //假如是AMS进程调用此办法,则直接回来已授权状况
        if (pid == MY_PID) {
            return PackageManager.PERMISSION_GRANTED;
        }
        return ActivityManager.checkComponentPermission(permission, uid,
                owningUid, exported);
    }
    /** @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);
        //假如是root用户或者是体系使用,直接回来已授权状况
        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.
        //owningUid为刚刚咱们传的参数4,为-1,所以显然这儿不满意
        if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
            return PackageManager.PERMISSION_GRANTED;
        }
        // If the target is not exported, then nobody else can get to it.
        //exported为刚刚咱们传的参数5,为true,所以显然这儿不满意,这儿的意思是假如方针进程不对外开放,则任何方针都无法访问
        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 {
            //经过PackageManagerService查看权限
            return AppGlobals.getPackageManager()
                    .checkUidPermission(permission, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    //省掉部分代码
}

先是处理了一些特殊状况的逻辑,终究权限判别交由frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java来完成

public class PackageManagerService extends IPackageManager.Stub
        implements PackageSender {
    //省掉部分代码
	@Override
    public int checkUidPermission(String permName, int uid) {
        final CheckPermissionDelegate checkPermissionDelegate;
        synchronized (mPackages) {
            if (mCheckPermissionDelegate == null)  {
                return checkUidPermissionImpl(permName, uid);
            }
            checkPermissionDelegate = mCheckPermissionDelegate;
        }
        //终究都履行checkUidPermissionImpl()
        return checkPermissionDelegate.checkUidPermission(permName, uid,
                PackageManagerService.this::checkUidPermissionImpl);
    }
    private int checkUidPermissionImpl(String permName, int uid) {
        synchronized (mPackages) {
            //先获取packageName
            final String[] packageNames = getPackagesForUid(uid);
            PackageParser.Package pkg = null;
            final int N = packageNames == null ? 0 : packageNames.length;
            for (int i = 0; pkg == null && i < N; i++) {
                pkg = mPackages.get(packageNames[i]);
            }
            //履行PermissionManagerServiceInternal的checkUidPermission()
            return mPermissionManager.checkUidPermission(permName, pkg, uid, getCallingUid());
        }
    }
    //省掉部分代码
}

能够看到,终究会履行PermissionManagerServiceInternalcheckUidPermission()checkUidPermission()是一个抽象办法,由PermissionManagerServiceInternal的子类PermissionManagerService.PermissionManagerServiceInternalImpl来完成

/**
 * Manages all permissions and handles permissions related tasks.
 */
public class PermissionManagerService {
    //省掉部分代码
    /**
     * Built-in permissions. Read from system configuration files. Mapping is from
     * UID to permission name.
     */
    private final SparseArray<ArraySet<String>> mSystemPermissions;
	private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {    
        //省掉部分代码
		@Override
        public int checkUidPermission(String permName, PackageParser.Package pkg, int uid,
                int callingUid) {
            //履行PermissionManagerService的checkUidPermission()办法
            return PermissionManagerService.this.checkUidPermission(permName, pkg, uid, callingUid);
        }
        //省掉部分代码
    }
    private int checkUidPermission(String permName, PackageParser.Package pkg, int uid,
            int callingUid) {
        //获取调用此Service的进程uid,也便是调用者的uid
        final int callingUserId = UserHandle.getUserId(callingUid);
        //callingUserId是否为即时使用,我称之为快使用,免安装的那种
        final boolean isCallerInstantApp =
                mPackageManagerInt.getInstantAppPackageName(callingUid) != null;
        //uid是否为即时使用,我称之为快使用,免安装的那种
        final boolean isUidInstantApp =
                mPackageManagerInt.getInstantAppPackageName(uid) != null;
        //获取请求权限的进程id,假如是微信请求权限,则uid指微信,经过日志打印得知,userId与callingUserId相等
        final int userId = UserHandle.getUserId(uid);
        if (!mUserManagerInt.exists(userId)) {
            return PackageManager.PERMISSION_DENIED;
        }
        if (pkg != null) {
            //非常规场景的处理
            if (pkg.mSharedUserId != null) {
                if (isCallerInstantApp) {
                    return PackageManager.PERMISSION_DENIED;
                }
            } else if (mPackageManagerInt.filterAppAccess(pkg, callingUid, callingUserId)) {
                return PackageManager.PERMISSION_DENIED;
            }
            //获取该使用的授权状况,授权状况封装在PermissionState方针傍边
            final PermissionsState permissionsState =
                    ((PackageSetting) pkg.mExtras).getPermissionsState();
            //假如已经授权,则回来PERMISSION_GRANTED
            if (permissionsState.hasPermission(permName, userId)) {
                if (isUidInstantApp) {
                    if (mSettings.isPermissionInstant(permName)) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                } else {
                    return PackageManager.PERMISSION_GRANTED;
                }
            }
            //假如同权限组中有其他的权限已经授权了,则该组其它权限也直接授权,比方ACCESS_FINE_LOCATION授权了,ACCESS_COURSE_LOCATION也会自动授权
            if (isImpliedPermissionGranted(permissionsState, permName, userId)) {
                return PackageManager.PERMISSION_GRANTED;
            }
        } else {
            //假如pkg为空,阐明PMS没有扫描到此安装包,此逻辑使用app不必考虑,经过日志,也没有走到此处
            ArraySet<String> perms = mSystemPermissions.get(uid);
            if (perms != null) {
                if (perms.contains(permName)) {
                    return PackageManager.PERMISSION_GRANTED;
                }
                if (FULLER_PERMISSION_MAP.containsKey(permName)
                        && perms.contains(FULLER_PERMISSION_MAP.get(permName))) {
                    return PackageManager.PERMISSION_GRANTED;
                }
            }
        }
        //都不满意则回来PERMISSION_DENIED
        return PackageManager.PERMISSION_DENIED;
    }
    //省掉部分代码
}

先从PackageParser.Package中读取mExtral字段,此字段为PackageSetting方针,再经过PackageSetting读取当时使用授权状况PermissionStatePackageParser.Package表示从磁盘读取的APK文件的完好信息(PMS在初始化时会扫描磁盘,这儿不做详细剖析),咱们知道一个APK文件包含许多信息,包名,版本号,一切注册的组件,需求请求的权限等等,详细可参考manifest文件和gradle文件,而咱们的权限信息就在mExtral字段傍边,而mExtral是一个PackageSetting方针,涉及到安装包装备变更的数据都保存在此方针中,其中咱们经过getPermissionsState()拿到授权状况PermissionsState,然后经过hasPermission()判别当时请求的权限是否已经授权

public final class PermissionsState {
    //省掉部分代码
    @GuardedBy("mLock")
    private ArrayMap<String, PermissionData> mPermissions;
	/**
     * 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);
        }
    }
    //省掉部分代码
}

由于一个ap或许涉及到多个权限请求,所以PermissionsState里界说了一个ArrayMap来保存一切权限的授权状况,map的key为权限称号,value为PermissionDataPermissionData里边界说了一个SparseArray<PermissionsState.PermissionState>,保存一切用户对当时app指定权限的授权状况

    private static final class PermissionData {
        private final BasePermission mPerm;
        private SparseArray<PermissionState> mUserStates = new SparseArray<>();
        public PermissionData(BasePermission perm) {
            mPerm = perm;
        }
        public PermissionData(PermissionData other) {
            this(other.mPerm);
            final int otherStateCount = other.mUserStates.size();
            for (int i = 0; i < otherStateCount; i++) {
                final int otherUserId = other.mUserStates.keyAt(i);
                PermissionState otherState = other.mUserStates.valueAt(i);
                mUserStates.put(otherUserId, new PermissionState(otherState));
            }
        }
        //这儿考虑了多用户的状况
        public boolean isGranted(int userId) {
            if (isInstallPermission()) {
                userId = UserHandle.USER_ALL;
            }
            PermissionState userState = mUserStates.get(userId);
            if (userState == null) {
                return false;
            }
            return userState.mGranted;
        }
        //假如用户点击了答应授权,则调用此办法设置
        public boolean grant(int userId) {
            if (!isCompatibleUserId(userId)) {
                return false;
            }
            if (isGranted(userId)) {
                return false;
            }
            PermissionState userState = mUserStates.get(userId);
            if (userState == null) {
                userState = new PermissionState(mPerm.getName());
                mUserStates.put(userId, userState);
            }
            userState.mGranted = true;
            return true;
        }
        //省掉部分代码
    }

PermissionsState.PermissionState则是界说了权限的称号和权限的授权状况

public final class PermissionsState {
    //省掉部分代码
	public static final class PermissionState {
        //权限称号
        private final String mName;
        //是否授权
        private boolean mGranted;
        private int mFlags;
        public PermissionState(String name) {
            mName = name;
        }
        public PermissionState(PermissionState other) {
            mName = other.mName;
            mGranted = other.mGranted;
            mFlags = other.mFlags;
        }
        public boolean isDefault() {
            return !mGranted && mFlags == 0;
        }
        public String getName() {
            return mName;
        }
        public boolean isGranted() {
            return mGranted;
        }
        public int getFlags() {
            return mFlags;
        }
    }
}

以上是Context.checkPermission()的流程

请求权限

下面再来看看Activity.requestPermissions()的流程,fragment的权限请求也是走的宿主Activity的权限请求流程

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
    //省掉部分代码
	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 intent = getPackageManager().buildRequestPermissionsIntent(permissions);
        //发动Activity
        startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
        mHasCurrentPermissionsRequest = true;
    }
    //省掉部分代码
}

经过PackageManager构建了一个Intent,然后发动了一个Activity

public abstract class PackageManager {
    //省掉部分代码
    @SystemApi
    public static final String ACTION_REQUEST_PERMISSIONS =
            "android.content.pm.action.REQUEST_PERMISSIONS";
	public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
        if (ArrayUtils.isEmpty(permissions)) {
           throw new IllegalArgumentException("permission cannot be null or empty");
        }
        //隐式Intent,注册了ACTION_REQUEST_PERMISSIONS的Activity能够处理此Intent
        Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
        intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);
        intent.setPackage(getPermissionControllerPackageName());
        return intent;
    }
    //省掉部分代码
}

PackageManager发动了一个隐式的Intent,ACTION为android.content.pm.action.REQUEST_PERMISSIONS,那么注册了该ACTION的即可处理此Intent,而GrantPermissionsActivity就注册了此ACTION

        <activity android:name="com.android.packageinstaller.permission.ui.GrantPermissionsActivity"
                android:configChanges="keyboardHidden|screenSize"
                android:excludeFromRecents="true"
                android:theme="@style/GrantPermissions"
                android:visibleToInstantApps="true"
                android:inheritShowWhenLocked="true">
            <intent-filter android:priority="1">
            	<!--注册了方针action-->
                <action android:name="android.content.pm.action.REQUEST_PERMISSIONS" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

能够看到此Activity的theme设置为了GrantPermissions,而此theme的界说为

    <style name="GrantPermissions"
           parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- The following attributes change the behavior of the dialog, hence they should not be
             themed -->
        <item name="android:windowIsTranslucent">true</item>
    </style>

风格为对话框,没有窗口标题,透明布景,沉浸式状况栏,不便是咱们弹出的授权对话框吗

图1

浅析Android10动态授权流程

再看看Activity的处理

public class GrantPermissionsActivity extends Activity
        implements GrantPermissionsViewHandler.ResultListener {
    //省掉部分代码
    private GrantPermissionsViewHandler mViewHandler;
    private String[] mRequestedPermissions;
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        //省掉部分代码
        //获取要请求的权限
        mRequestedPermissions = getIntent().getStringArrayExtra(
                PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
         // Don't allow legacy apps to request runtime permissions.
        //6.0以下不需求动态授权
        if (callingPackageInfo.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
            // Returning empty arrays means a cancellation.
            mRequestedPermissions = new String[0];
            setResultAndFinish();
            return;
        }
        //省掉部分代码
        //依据不同的设备创立不同的Handler
        if (DeviceUtils.isTelevision(this)) {
            mViewHandler = new com.android.packageinstaller.permission.ui.television
                    .GrantPermissionsViewHandlerImpl(this,
                    mCallingPackage).setResultListener(this);
        } else if (DeviceUtils.isWear(this)) {
            mViewHandler = new GrantPermissionsWatchViewHandler(this).setResultListener(this);
        } else if (DeviceUtils.isAuto(this)) {
            mViewHandler = new GrantPermissionsAutoViewHandler(this, mCallingPackage, userHandle)
                    .setResultListener(this);
        } else {
            mViewHandler = new com.android.packageinstaller.permission.ui.handheld
                    .GrantPermissionsViewHandlerImpl(this, mCallingPackage, userHandle)
                    .setResultListener(this);
        }
        //省掉部分代码
        //设置页面布局
        setContentView(mViewHandler.createView());
        //省掉部分代码
}

页面布局文件的创立在对应的Handler的createView()办法傍边,由于我是在手机上测试的,所以创立的是GrantPermissionsViewHandlerImpl

public class GrantPermissionsViewHandlerImpl implements GrantPermissionsViewHandler,
        OnClickListener {
    //省掉部分代码
	@Override
    public View createView() {
        mRootView = (ViewGroup) LayoutInflater.from(mActivity)
                .inflate(R.layout.grant_permissions, null);
        int h = mActivity.getResources().getDisplayMetrics().heightPixels;
        mRootView.setMinimumHeight(h);
		//省掉部分代码
        return mRootView;
    }
    //省掉部分代码
}

翻开grant_permissions.xml文件,便是图1中的布局,直接看点击答应和回绝之后的处理

public class GrantPermissionsViewHandlerImpl implements GrantPermissionsViewHandler,
        OnClickListener {
    //省掉部分代码
	@Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.permission_allow_button:
                //点击答应
                if (mResultListener != null) {
                    view.performAccessibilityAction(
                            AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
                    mResultListener.onPermissionGrantResult(mGroupName, GRANTED_ALWAYS);
                }
                break;
            case R.id.permission_allow_always_button:
                //点击一直答应
                if (mResultListener != null) {
                    view.performAccessibilityAction(
                            AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
                    mResultListener.onPermissionGrantResult(mGroupName, GRANTED_ALWAYS);
                }
                break;
            case R.id.permission_allow_foreground_only_button:
                //点击运行期间答应
                if (mResultListener != null) {
                    view.performAccessibilityAction(
                            AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
                    mResultListener.onPermissionGrantResult(mGroupName,
                            GRANTED_FOREGROUND_ONLY);
                }
                break;
            case R.id.permission_deny_button:
                //点击回绝
                if (mResultListener != null) {
                    view.performAccessibilityAction(
                            AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
                    mResultListener.onPermissionGrantResult(mGroupName, DENIED);
                }
                break;
            case R.id.permission_deny_and_dont_ask_again_button:
                //点击回绝且不再提示
                if (mResultListener != null) {
                    view.performAccessibilityAction(
                            AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
                    mResultListener.onPermissionGrantResult(mGroupName,
                            DENIED_DO_NOT_ASK_AGAIN);
                }
                break;
			//省掉部分代码
        }
    }
    //省掉部分代码
}

无论点击什么按钮,都经过ResultListener进行回调,并带着用户挑选的结果,GrantPermissionsActivity完成了这个接口,看一下它的处理

public class GrantPermissionsActivity extends Activity
        implements GrantPermissionsViewHandler.ResultListener {
    //省掉部分代码
	@Override
    public void onPermissionGrantResult(String name,
            @GrantPermissionsViewHandler.Result int result) {
        //记载日志
        logGrantPermissionActivityButtons(name, result);
        GroupState foregroundGroupState = getForegroundGroupState(name);
        GroupState backgroundGroupState = getBackgroundGroupState(name);
        //假如设备处于锁屏状况,先免除锁屏
        if (result == GRANTED_ALWAYS || result == GRANTED_FOREGROUND_ONLY
                || result == DENIED_DO_NOT_ASK_AGAIN) {
            KeyguardManager kgm = getSystemService(KeyguardManager.class);
            if (kgm.isDeviceLocked()) {
                kgm.requestDismissKeyguard(this, new KeyguardManager.KeyguardDismissCallback() {
                            @Override
                            public void onDismissError() {
                                Log.e(LOG_TAG, "Cannot dismiss keyguard perm=" + name + " result="
                                        + result);
                            }
                            @Override
                            public void onDismissCancelled() {
                                // do nothing (i.e. stay at the current permission group)
                            }
                            @Override
                            public void onDismissSucceeded() {
                                // Now the keyguard is dismissed, hence the device is not locked
                                // anymore
                                //解锁后持续履行此办法
                                onPermissionGrantResult(name, result);
                            }
                        });
                return;
            }
        }
		//依据用户挑选履行对应的动作
        switch (result) {
            case GRANTED_ALWAYS :
                if (foregroundGroupState != null) {
                    onPermissionGrantResultSingleState(foregroundGroupState, true, false);
                }
                if (backgroundGroupState != null) {
                    onPermissionGrantResultSingleState(backgroundGroupState, true, false);
                }
                break;
            case GRANTED_FOREGROUND_ONLY :
                if (foregroundGroupState != null) {
                    onPermissionGrantResultSingleState(foregroundGroupState, true, false);
                }
                if (backgroundGroupState != null) {
                    onPermissionGrantResultSingleState(backgroundGroupState, false, false);
                }
                break;
            case DENIED :
                if (foregroundGroupState != null) {
                    onPermissionGrantResultSingleState(foregroundGroupState, false, false);
                }
                if (backgroundGroupState != null) {
                    onPermissionGrantResultSingleState(backgroundGroupState, false, false);
                }
                break;
            case DENIED_DO_NOT_ASK_AGAIN :
                if (foregroundGroupState != null) {
                    onPermissionGrantResultSingleState(foregroundGroupState, false, true);
                }
                if (backgroundGroupState != null) {
                    onPermissionGrantResultSingleState(backgroundGroupState, false, true);
                }
                break;
        }
        if (!showNextPermissionGroupGrantRequest()) {
            setResultAndFinish();
        }
    }
    //省掉部分代码
}

能够看到终究都会履行onPermissionGrantResultSingleState()

    private void onPermissionGrantResultSingleState(GroupState groupState, boolean granted,
            boolean doNotAskAgain) {
        if (groupState != null && groupState.mGroup != null
                && groupState.mState == GroupState.STATE_UNKNOWN) {
            if (granted) {
                //用户答应授权
                groupState.mGroup.grantRuntimePermissions(doNotAskAgain,
                        groupState.affectedPermissions);
                groupState.mState = GroupState.STATE_ALLOWED;
                reportRequestResult(groupState.affectedPermissions,
                        PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED);
            } else {
                //用户回绝授权
                groupState.mGroup.revokeRuntimePermissions(doNotAskAgain,
                        groupState.affectedPermissions);
                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);
            }
        }
    }

看看答应授权的逻辑

	public boolean grantRuntimePermissions(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 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) {
                    // Now the apps can ask for the permission as the user
                    // no longer has it fixed in a denied state.
                    if (permission.isUserFixed() || permission.isUserSet()) {
                        permission.setUserFixed(false);
                        permission.setUserSet(false);
                    }
                }
            } else {
                // Legacy apps cannot have a not granted permission but just in case.
                if (!permission.isGranted()) {
                    continue;
                }
                // If the permissions has no corresponding app op, then it is a
                // third-party one and we do not offer toggling of such permissions.
                if (permission.affectsAppOp()) {
                    if (!permission.isAppOpAllowed()) {
                        permission.setAppOpAllowed(true);
                        // Legacy apps do not know that they have to retry access to a
                        // resource due to changes in runtime permissions (app ops in this
                        // case). Therefore, we restart them on app op change, so they
                        // can pick up the change.
                        killApp = true;
                    }
                    // Mark that the permission should not be be granted on upgrade
                    // when the app begins supporting runtime permissions.
                    if (permission.shouldRevokeOnUpgrade()) {
                        permission.setRevokeOnUpgrade(false);
                    }
                }
                // Granting a permission explicitly means the user already
                // reviewed it so clear the review flag on every grant.
                if (permission.isReviewRequired()) {
                    permission.unsetReviewRequired();
                }
            }
            // If we newly grant background access to the fine location, double-guess the user some
            // time later if this was really the right choice.
            if (!wasGranted && permission.isGrantedIncludingAppOp()) {
                if (permission.getName().equals(ACCESS_FINE_LOCATION)) {
                    Permission bgPerm = permission.getBackgroundPermission();
                    if (bgPerm != null) {
                        if (bgPerm.isGrantedIncludingAppOp()) {
                            mTriggerLocationAccessCheckOnPersist = true;
                        }
                    }
                } else if (permission.getName().equals(ACCESS_BACKGROUND_LOCATION)) {
                    ArrayList<Permission> fgPerms = permission.getForegroundPermissions();
                    if (fgPerms != null) {
                        int numFgPerms = fgPerms.size();
                        for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
                            Permission fgPerm = fgPerms.get(fgPermNum);
                            if (fgPerm.getName().equals(ACCESS_FINE_LOCATION)) {
                                if (fgPerm.isGrantedIncludingAppOp()) {
                                    mTriggerLocationAccessCheckOnPersist = true;
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (!mDelayChanges) {
            //这儿很重要,将授权信息耐久化保存到本地
            persistChanges(false);
            if (killApp) {
                killApp(KILL_REASON_APP_OP_CHANGE);
            }
        }
        return wasAllGranted;
    }

授权过程便是本地数据装备的过程,最后有一个逻辑很关键,便是将授权信息进行耐久化保存,由于当咱们关机重启后,需求恢复各个app的授权信息,看看保存到哪儿了

void persistChanges(boolean mayKillBecauseOfAppOpsChange) {
        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) {
                        mPackageManager.revokeRuntimePermission(mPackageInfo.packageName,
                                permission.getName(), mUserHandle);
                    }
                }
            }
            int flags = (permission.isUserSet() ? PackageManager.FLAG_PERMISSION_USER_SET : 0)
                    | (permission.isUserFixed() ? PackageManager.FLAG_PERMISSION_USER_FIXED : 0)
                    | (permission.shouldRevokeOnUpgrade()
                    ? PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE : 0)
                    | (permission.isPolicyFixed() ? PackageManager.FLAG_PERMISSION_POLICY_FIXED : 0)
                    | (permission.isReviewRequired()
                    ? PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED : 0);
            //更新权限标识位,这儿是去更新PMS里边当时app的权限装备
            mPackageManager.updatePermissionFlags(permission.getName(),
                    mPackageInfo.packageName,
                    PackageManager.FLAG_PERMISSION_USER_SET
                            | PackageManager.FLAG_PERMISSION_USER_FIXED
                            | PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE
                            | PackageManager.FLAG_PERMISSION_POLICY_FIXED
                            | PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED,
                    flags, mUserHandle);
            if (permission.affectsAppOp()) {
                if (!permission.isSystemFixed()) {
                    // Enabling/Disabling an app op may put the app in a situation in which it has
                    // a handle to state it shouldn't have, so we have to kill the app. This matches
                    // the revoke runtime permission behavior.
                    if (permission.isAppOpAllowed()) {
                        shouldKillApp |= allowAppOp(permission, uid);
                    } else {
                        shouldKillApp |= disallowAppOp(permission, uid);
                    }
                }
            }
        }
        if (mayKillBecauseOfAppOpsChange && shouldKillApp) {
            killApp(KILL_REASON_APP_OP_CHANGE);
        }
        if (mTriggerLocationAccessCheckOnPersist) {
            new LocationAccessCheck(mContext, null).checkLocationAccessSoon();
            mTriggerLocationAccessCheckOnPersist = false;
        }
    }

这儿经过AIDL,将当时授权信息发送给PMS,使得PMS中保存的当时app的授权信息得以更新

    @Override
    public void updatePermissionFlags(String permissionName, String packageName,
            int flagMask, int flagValues, UserHandle user) {
        try {
        	//跨进程调用,履行PackageManagerService的updatePermissionFlags()
            mPM.updatePermissionFlags(permissionName, packageName, flagMask,
                    flagValues,
                    mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q,
                    user.getIdentifier());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

看看PackageManagerService的处理

    @Override
    public void updatePermissionFlags(String permName, String packageName, int flagMask,
            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
        int callingUid = getCallingUid();
        boolean overridePolicy = false;
        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
            long callingIdentity = Binder.clearCallingIdentity();
            try {
                if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
                    if (checkAdjustPolicyFlagPermission) {
                        mContext.enforceCallingOrSelfPermission(
                                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
                                "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
                                        + " to change policy flags");
                    } else if (!hasTargetSdkInUidLowerThan(callingUid, Build.VERSION_CODES.Q)) {
                        throw new IllegalArgumentException(
                                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
                                        + " to be checked for packages targeting "
                                        + Build.VERSION_CODES.Q + " or later when changing policy "
                                        + "flags");
                    }
                    overridePolicy = true;
                }
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
            }
        }
		//经过PermissionManagerService操作
        mPermissionManager.updatePermissionFlags(
                permName, packageName, flagMask, flagValues, callingUid, userId,
                overridePolicy, mPermissionCallback);
    }

终究更新的是PermissionManagerService傍边的数据

	private void updatePermissionFlags(String permName, String packageName, int flagMask,
            int flagValues, int callingUid, int userId, boolean overridePolicy,
            PermissionCallback callback) {
        //省掉部分代码
        //先获取PackageParser.Package
        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
        //省掉部分代码
        //更新Package的mExtras
        final PackageSetting ps = (PackageSetting) pkg.mExtras;
        final PermissionsState permissionsState = ps.getPermissionsState();
        final boolean hadState =
                permissionsState.getRuntimePermissionState(permName, userId) != null;
        final boolean permissionUpdated =
                permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
        if (permissionUpdated && bp.isRuntime()) {
            notifyRuntimePermissionStateChanged(packageName, userId);
        }
        if (permissionUpdated && callback != null) {
            // Install and runtime permissions are stored in different places,
            // so figure out what permission changed and persist the change.
            if (permissionsState.getInstallPermissionState(permName) != null) {
                //通知安装权限更新,便是不需求动态授权的权限
                callback.onInstallPermissionUpdated();
            } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
                    || hadState) {
                //通知动态权限状况更新
                callback.onPermissionUpdated(new int[] { userId }, false);
            }
        }
    }

能够看到,终究更新的是PackageParser.PackagemExtras字段,上面咱们剖析知道,在查看权限时,也是读取的PackageParser.PackagemExtras字段,这儿就跟前面的逻辑相照应了,更新完之后,经过callback进行回调,履行耐久化存储

        @Override
        public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
            synchronized (mPackages) {
                for (int userId : updatedUserIds) {
                    mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
                }
            }
        }
    public void writeRuntimePermissionsForUserLPr(int userId, boolean sync) {
        if (sync) {
            mRuntimePermissionsPersistence.writePermissionsForUserSyncLPr(userId);
        } else {
            mRuntimePermissionsPersistence.writePermissionsForUserAsyncLPr(userId);
        }
    }
	private void writePermissionsSync(int userId) {
            //界说耐久化保存途径
            AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId),
                    "package-perms-" + userId);
            //省掉部分代码
            FileOutputStream out = null;
            try {
             	//省掉部分代码
                //保存到本地
                destination.finishWrite(out);
                if (Build.FINGERPRINT.equals(fingerprint)) {
                    mDefaultPermissionsGranted.put(userId, true);
                }
            // Any error while writing is fatal.
            } catch (Throwable t) {
                Slog.wtf(PackageManagerService.TAG,
                        "Failed to write settings, restoring backup", t);
                destination.failWrite(out);
            } finally {
                IoUtils.closeQuietly(out);
            }
    }
	//文件名
	private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
	//获取途径
    private File getUserRuntimePermissionsFile(int userId) {
        // TODO: Implement a cleaner solution when adding tests.
        // This instead of Environment.getUserSystemDirectory(userId) to support testing.
        File userDir = new File(new File(mSystemDir, "users"), Integer.toString(userId));
        File file = new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME);
        Log.d("jasonwan", "getUserRuntimePermissionsFile: file="+file.getAbsolutePath());
        return file;
    }

经过log打印得知,权限文件途径位于/data/system/users/0/runtime-permissions.xml,咱们从设备中导出此文件翻开看看长啥样

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<runtime-permissions version="8" fingerprint="qti/trinket/trinket:10/QKQ1.200816.002/2211:userdebug/test-keys">
  <pkg name="com.android.externalstorage">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
  </pkg>
  <pkg name="com.android.companiondevicemanager">
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="30" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="false" flags="b0" />
    <item name="android.permission.ACCESS_BACKGROUND_LOCATION" granted="true" flags="3030" />
  </pkg>
  <pkg name="com.android.quicksearchbox">
    <item name="android.permission.READ_CONTACTS" granted="false" flags="300" />
  </pkg>
  <pkg name="com.android.soundrecorder">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="false" flags="2380" />
    <item name="android.permission.READ_PHONE_STATE" granted="false" flags="300" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="false" flags="2300" />
    <item name="android.permission.RECORD_AUDIO" granted="true" flags="320" />
    <item name="android.permission.ACCESS_MEDIA_LOCATION" granted="false" flags="380" />
  </pkg>
  <pkg name="com.android.contacts">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="false" flags="2300" />
    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="320" />
    <item name="android.permission.CALL_PHONE" granted="true" flags="320" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="320" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="320" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="320" />
    <item name="android.permission.ACCESS_MEDIA_LOCATION" granted="false" flags="380" />
  </pkg>
  <pkg name="com.android.mms">
    <item name="android.permission.READ_SMS" granted="true" flags="3320" />
    <item name="android.permission.RECEIVE_WAP_PUSH" granted="true" flags="3320" />
    <item name="android.permission.RECEIVE_MMS" granted="true" flags="3320" />
    <item name="android.permission.RECEIVE_SMS" granted="true" flags="3320" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="33a0" />
    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="320" />
    <item name="android.permission.SEND_SMS" granted="true" flags="3320" />
    <item name="android.permission.CALL_PHONE" granted="true" flags="320" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="320" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3320" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="320" />
    <item name="android.permission.ACCESS_MEDIA_LOCATION" granted="true" flags="3a0" />
  </pkg>
  <pkg name="com.android.launcher3">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="false" flags="2100" />
    <item name="android.permission.READ_PHONE_STATE" granted="false" flags="100" />
    <item name="android.permission.CALL_PHONE" granted="false" flags="100" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="false" flags="2100" />
  </pkg>
  <pkg name="com.android.settings.intelligence">
    <item name="android.permission.READ_PHONE_STATE" granted="false" flags="100" />
  </pkg>
  <pkg name="com.android.calendar">
    <item name="android.permission.READ_CALENDAR" granted="true" flags="320" />
    <item name="android.permission.WRITE_CALENDAR" granted="true" flags="320" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="320" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="320" />
  </pkg>
  <pkg name="com.android.sharedstoragebackup">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="30b0" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
  </pkg>
  <pkg name="com.android.printspooler">
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="30" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="30" />
  </pkg>
    <!-- 测试Demo-->
  <pkg name="com.jason.nodetest">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="b00" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="b00" />
  </pkg>
  <pkg name="com.android.email">
    <item name="android.permission.READ_CALENDAR" granted="true" flags="320" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="false" flags="2380" />
    <item name="android.permission.READ_PHONE_STATE" granted="false" flags="300" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="320" />
    <item name="android.permission.WRITE_CALENDAR" granted="true" flags="320" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="320" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="false" flags="2300" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="320" />
    <item name="android.permission.ACCESS_MEDIA_LOCATION" granted="false" flags="380" />
  </pkg>
  <pkg name="com.android.music">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3320" />
    <item name="android.permission.READ_PHONE_STATE" granted="false" flags="300" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3320" />
    <item name="android.permission.ACCESS_MEDIA_LOCATION" granted="true" flags="3a0" />
  </pkg>
  <shared-user name="android.media">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
  </shared-user>
  <shared-user name="android.uid.systemui">
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="30" />
    <item name="android.permission.CAMERA" granted="true" flags="30" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="30" />
    <item name="android.permission.RECORD_AUDIO" granted="true" flags="30" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="30" />
  </shared-user>
  <shared-user name="android.uid.nfc">
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="30b0" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="30" />
  </shared-user>
  <shared-user name="android.uid.bluetooth">
    <item name="android.permission.READ_SMS" granted="true" flags="3030" />
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="30" />
    <item name="com.android.email.permission.READ_ATTACHMENT" granted="true" flags="1030" />
    <item name="android.permission.RECEIVE_SMS" granted="true" flags="3030" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="30" />
    <item name="android.permission.SEND_SMS" granted="true" flags="3030" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="1030" />
    <item name="android.permission.WRITE_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="1030" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="1030" />
  </shared-user>
  <shared-user name="android.uid.shared">
    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="30" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="30" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="30" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="30" />
  </shared-user>
  <shared-user name="android.uid.system">
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="1030" />
    <item name="android.permission.RECEIVE_WAP_PUSH" granted="true" flags="3030" />
    <item name="android.permission.RECEIVE_SMS" granted="true" flags="3030" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="false" flags="10b0" />
    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="1030" />
    <item name="android.permission.SEND_SMS" granted="true" flags="3030" />
    <item name="android.permission.CALL_PHONE" granted="true" flags="1330" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="1330" />
    <item name="android.permission.CAMERA" granted="true" flags="1330" />
    <item name="android.permission.WRITE_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.PROCESS_OUTGOING_CALLS" granted="true" flags="3030" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="30" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.RECORD_AUDIO" granted="true" flags="1330" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="1330" />
    <item name="android.permission.ACCESS_BACKGROUND_LOCATION" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_MEDIA_LOCATION" granted="true" flags="1030" />
  </shared-user>
  <shared-user name="android.uid.phone">
    <item name="android.permission.READ_SMS" granted="true" flags="3030" />
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="30" />
    <item name="android.permission.RECEIVE_SMS" granted="true" flags="3030" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="1030" />
    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="30" />
    <item name="android.permission.SEND_SMS" granted="true" flags="3030" />
    <item name="android.permission.CALL_PHONE" granted="true" flags="30" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="30" />
    <item name="android.permission.CAMERA" granted="true" flags="1030" />
    <item name="android.permission.WRITE_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.USE_SIP" granted="true" flags="1030" />
    <item name="android.permission.PROCESS_OUTGOING_CALLS" granted="true" flags="3030" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="1030" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.RECORD_AUDIO" granted="true" flags="1030" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="30" />
    <item name="android.permission.ACCESS_BACKGROUND_LOCATION" granted="true" flags="3030" />
    <item name="com.android.voicemail.permission.ADD_VOICEMAIL" granted="true" flags="1030" />
  </shared-user>
  <shared-user name="android.uid.shell">
    <item name="android.permission.READ_SMS" granted="true" flags="3030" />
    <item name="android.permission.READ_CALENDAR" granted="true" flags="30" />
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="30" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="false" flags="30" />
    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="30" />
    <item name="android.permission.SEND_SMS" granted="true" flags="3030" />
    <item name="android.permission.CALL_PHONE" granted="true" flags="30" />
    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="30" />
    <item name="android.permission.WRITE_CALENDAR" granted="true" flags="30" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="30" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3030" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="30" />
  </shared-user>
  <shared-user name="android.uid.calendar">
    <item name="android.permission.READ_CALENDAR" granted="true" flags="30" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="30a0" />
    <item name="android.permission.WRITE_CALENDAR" granted="true" flags="30" />
    <item name="android.permission.GET_ACCOUNTS" granted="true" flags="20" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="3020" />
  </shared-user>
  <shared-user name="com.android.emergency.uid">
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="3030" />
    <item name="android.permission.CALL_PHONE" granted="true" flags="30" />
    <item name="android.permission.READ_CONTACTS" granted="true" flags="30" />
  </shared-user>
</runtime-permissions>

能够看到此文件保存便是各个app的动态权限授权状况,安装权限不在此文件中,咱们的测试demo包名为com.jason.nodetest,能够看到咱们只答应读存储卡权限后,读写权限均为已授权。

相同,当体系重启后,PackageManagerService会初始化并发动,初始化时会从UserServiceManager中获取读取的权限数据

public class PackageManagerService extends IPackageManager.Stub
        implements PackageSender {
    //省掉部分代码
	public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        	//省掉部分代码
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
        	//UserManager创立用户时会去读取用户装备文件,其中就包含runtime-permissions.xml文件
            mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
	        //省掉部分代码
    }
    //省掉部分代码
}
    boolean readLPw(@NonNull List<UserInfo> users) {
    	//省掉部分代码
       	for (UserInfo user : users) {
            //读取一切用户装备信息
            mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
        }
		//省掉部分代码
    }
		@GuardedBy("Settings.this.mLock")
        public void readStateForUserSyncLPr(int userId) {
            //获取runtime-permissions.xml文件
            File permissionsFile = getUserRuntimePermissionsFile(userId);
            if (!permissionsFile.exists()) {
                return;
            }
            FileInputStream in;
            try {
                in = new AtomicFile(permissionsFile).openRead();
            } catch (FileNotFoundException fnfe) {
                Slog.i(PackageManagerService.TAG, "No permissions state");
                return;
            }
            try {
                XmlPullParser parser = Xml.newPullParser();
                parser.setInput(in, null);
                //解析runtime-permissions.xml文件
                parseRuntimePermissionsLPr(parser, userId);
            } catch (XmlPullParserException | IOException e) {
                throw new IllegalStateException("Failed parsing permissions file: "
                        + permissionsFile , e);
            } finally {
                IoUtils.closeQuietly(in);
            }
        }
		@GuardedBy("Settings.this.mLock")
        private void parseRuntimePermissionsLPr(XmlPullParser parser, int userId)
                throws IOException, XmlPullParserException {
            final int outerDepth = parser.getDepth();
            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }
                switch (parser.getName()) {
                    case TAG_RUNTIME_PERMISSIONS: {
                        // If the permisions settings file exists but the version is not set this is
                        // an upgrade from P->Q. Hence mark it with the special UPGRADE_VERSION
                        int version = XmlUtils.readIntAttribute(parser, ATTR_VERSION,
                                UPGRADE_VERSION);
                        mVersions.put(userId, version);
                        String fingerprint = parser.getAttributeValue(null, ATTR_FINGERPRINT);
                        mFingerprints.put(userId, fingerprint);
                        final boolean defaultsGranted = Build.FINGERPRINT.equals(fingerprint);
                        mDefaultPermissionsGranted.put(userId, defaultsGranted);
                    } break;
                    case TAG_PACKAGE: {
                        String name = parser.getAttributeValue(null, ATTR_NAME);
                        PackageSetting ps = mPackages.get(name);
                        if (ps == null) {
                            Slog.w(PackageManagerService.TAG, "Unknown package:" + name);
                            XmlUtils.skipCurrentTag(parser);
                            continue;
                        }
                        parsePermissionsLPr(parser, ps.getPermissionsState(), userId);
                    } break;
                    case TAG_SHARED_USER: {
                        //读取shared-user标签,拿到包名
                        String name = parser.getAttributeValue(null, ATTR_NAME);
                        SharedUserSetting sus = mSharedUsers.get(name);
                        if (sus == null) {
                            Slog.w(PackageManagerService.TAG, "Unknown shared user:" + name);
                            XmlUtils.skipCurrentTag(parser);
                            continue;
                        }
                        //解析shared-user下的一切item权限
                        parsePermissionsLPr(parser, sus.getPermissionsState(), userId);
                    } break;
                }
            }
        }
        private void parsePermissionsLPr(XmlPullParser parser, PermissionsState permissionsState,
                int userId) throws IOException, XmlPullParserException {
            final int outerDepth = parser.getDepth();
            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }
                switch (parser.getName()) {
                    case TAG_ITEM: {
                        //读取权限称号
                        String name = parser.getAttributeValue(null, ATTR_NAME);
                        BasePermission bp = mPermissions.getPermission(name);
                        if (bp == null) {
                            Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
                            XmlUtils.skipCurrentTag(parser);
                            continue;
                        }
						//读取权限授权状况
                        String grantedStr = parser.getAttributeValue(null, ATTR_GRANTED);
                        final boolean granted = grantedStr == null
                                || Boolean.parseBoolean(grantedStr);
						//读取权限的flag
                        String flagsStr = parser.getAttributeValue(null, ATTR_FLAGS);
                        final int flags = (flagsStr != null)
                                ? Integer.parseInt(flagsStr, 16) : 0;
						//给权限赋值
                        if (granted) {
                            permissionsState.grantRuntimePermission(bp, userId);
                            permissionsState.updatePermissionFlags(bp, userId,
                                        PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
                        } else {
                            permissionsState.updatePermissionFlags(bp, userId,
                                    PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
                        }
                    } break;
                }
            }

能够看到,从runtime-permissions.xml文件中读取的授权信息终究赋值给了PermissionsState,而咱们在查看权限时也是从PermissionState中获取的权限授权状况,这儿跟前面形成了闭环。

总结

以上便是Android 10动态授权的整个流程,简单总结下便是

1、Android发动,PackageManagerService发动,扫描APK获取一切权限

2、读取runtime-permissions.xml文件,获取动态权限授权状况,并将他赋值给PermissionState

3、用户查看权限,从PermissionState中获取方针权限的授权状况,并返给app

4、用户请求权限,依据用户的挑选,设置PermissionState中对应权限的状况,并耐久化存储到runtime-permissions.xml文件中