Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user’s approval by sending an intent with action ACTION_MANAGE_WRITE_ SETTINGS. The app can check whether it has this authorization by calling Settings.System.canWrite().
// 允许权限 @override publicvoidgrantRuntimePermission(String packageName, String name, finalint userId){ grantRuntimePermission(packageName, name, userId, false/* Only if not fixed by policy */); }
// 撤销权限 @Override publicvoidrevokeRuntimePermission(String packageName, String name, int userId){ revokeRuntimePermission(packageName, name, userId, false/* Only if not fixed by policy */); }
publicfinalvoidrequestPermissions(@NonNull String[] permissions, int requestCode){ if (requestCode < 0) { thrownew 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], newint[0]); return; } // 在PackageManager中去构建intent,主要是pm能够拿到action和intent的包名 Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions); startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null); mHasCurrentPermissionsRequest = true; }
1 2 3 4 5 6 7 8 9 10 11 12
public Intent buildRequestPermissionsIntent(@NonNull String[] permissions){ if (ArrayUtils.isEmpty(permissions)) { thrownew IllegalArgumentException("permission cannot be null or empty"); } // GrantPermissionsActivity的action Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS); // 声请的权限 intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions); // GrantPermissionsActivity所在的包,即PackageInstaller intent.setPackage(getPermissionControllerPackageName()); return intent; }
@Override publicvoidgrantRuntimePermission(String packageName, String name, finalint userId){ grantRuntimePermission(packageName, name, userId, false/* Only if not fixed by policy */); }
privatevoidgrantRuntimePermission(String packageName, String name, finalint userId, boolean overridePolicy){ if (!sUserManager.exists(userId)) {//确认user id存在 Log.e(TAG, "No such user:" + userId); return; } finalint callingUid = Binder.getCallingUid();//确定调用端app 的uid
synchronized (mPackages) { // //packageName 正确性 final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null) { thrownew IllegalArgumentException("Unknown package: " + packageName); } //permission name 正确性 final BasePermission bp = mSettings.mPermissions.get(name); if (bp == null) { thrownew IllegalArgumentException("Unknown permission: " + name); } // 获取ps,可以从里面拿到PermissionsState ps = (PackageSetting) pkg.mExtras; if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) { thrownew IllegalArgumentException("Unknown package: " + packageName); }
enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp); //app将该permission 注册到AndroidManifest中 //并且该permission 是Runtime 或者是development permission // If a permission review is required for legacy apps we represent // their permissions as always granted runtime ones since we need // to keep the review required permission flag per user while an // install permission's state is shared across all users. if (mPermissionReviewRequired //对于legacy apps不做处理 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) { return; }
final PermissionsState permissionsState = ps.getPermissionsState();
finalint flags = permissionsState.getPermissionFlags(name, userId); if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) { thrownew SecurityException("Cannot grant system fixed permission " + name + " for package " + packageName); } if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) { thrownew SecurityException("Cannot grant policy fixed permission " + name + " for package " + packageName); }
if (bp.isDevelopment()) { // Development permissions must be handled specially, since they are not // normal runtime permissions. For now they apply to all users. if (permissionsState.grantInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) { scheduleWriteSettingsLocked(); } return; }
if (ps.getInstantApp(userId) && !bp.isInstant()) { thrownew SecurityException("Cannot grant non-ephemeral permission" + name + " for package " + packageName); }
if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { Slog.w(TAG, "Cannot grant runtime permission to a legacy app"); return; }
// 对当前用户授权 finalint result = permissionsState.grantRuntimePermission(bp, userId); switch (result) { case PermissionsState.PERMISSION_OPERATION_FAILURE: { return; }
// Not critical if that is lost - app has to request again. mSettings.writeRuntimePermissionsForUserLPr(userId, false); }
// Only need to do this if user is initialized. Otherwise it's a new user // and there are no processes running as the user yet and there's no need // to make an expensive call to remount processes for the changed permissions. if (READ_EXTERNAL_STORAGE.equals(name) || WRITE_EXTERNAL_STORAGE.equals(name)) { finallong token = Binder.clearCallingIdentity(); try { if (sUserManager.isInitialized(userId)) { StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal.class); storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName); } } finally { Binder.restoreCallingIdentity(token); } } }
if (mWriteScheduled.get(userId)) { mHandler.removeMessages(userId);
// If enough time passed, write without holding off anymore. finallong lastNotWrittenMutationTimeMillis = mLastNotWrittenMutationTimesMillis .get(userId); finallong timeSinceLastNotWrittenMutationMillis = currentTimeMillis - lastNotWrittenMutationTimeMillis; if (timeSinceLastNotWrittenMutationMillis >= MAX_WRITE_PERMISSIONS_DELAY_MILLIS) { mHandler.obtainMessage(userId).sendToTarget(); return; }
// Hold off a bit more as settings are frequently changing. finallong maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0); finallong writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS, maxDelayMillis);