xref: /frameworks/base/core/java/android/app/Activity.java5076
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
5077 if (requestCode < 0) {
5078 throw new IllegalArgumentException("requestCode should be >= 0");
5079 }
5080 if (mHasCurrentPermissionsRequest) {
5081 Log.w(TAG, "Can request only one set of permissions at a time");
5082 // Dispatch the callback with empty arrays which means a cancellation.
5083 onRequestPermissionsResult(requestCode, new String[0], new int[0]);
5084 return;
5085 }
5086 Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
5087 startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
5088 mHasCurrentPermissionsRequest = true;
5089 }
xref: /frameworks/base/core/java/android/content/pm/PackageManager.java
2968 @SystemApi
2969 public static final String ACTION_REQUEST_PERMISSIONS =
2970 "android.content.pm.action.REQUEST_PERMISSIONS";
4263 @NonNull
4264 @UnsupportedAppUsage
4265 public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
4266 if (ArrayUtils.isEmpty(permissions)) {
4267 throw new IllegalArgumentException("permission cannot be null or empty");
4268 }
4269 Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
4270 intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);
4271 intent.setPackage(getPermissionControllerPackageName());
4272 return intent;
4273 }
xref: /packages/apps/PermissionController/AndroidManifest.xml
82 <activity android:name="com.android.packageinstaller.permission.ui.GrantPermissionsActivity"
83 android:configChanges="keyboardHidden|screenSize"
84 android:excludeFromRecents="true"
85 android:theme="@style/GrantPermissions"
86 android:visibleToInstantApps="true"
87 android:inheritShowWhenLocked="true">
88 <intent-filter android:priority="1">
89 <action android:name="android.content.pm.action.REQUEST_PERMISSIONS" />
90 <category android:name="android.intent.category.DEFAULT" />
91 </intent-filter>
92 </activity>
通过隐式意图跳转到GrantPermissionsActivity。
xref: /packages/apps/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
256 @Override
257 public void onCreate(Bundle icicle) {
258 super.onCreate(icicle);
259
260 if (icicle == null) {
261 mRequestId = new Random().nextLong();
262 } else {
263 mRequestId = icicle.getLong(KEY_REQUEST_ID);
264 }
265
266 getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
267
268 // Cache this as this can only read on onCreate, not later.
269 mCallingPackage = getCallingPackage();
270
271 SafetyNetLogger.logIfHasUndefinedPermissionGroup(getPackageManager(), mCallingPackage);
272
273 setFinishOnTouchOutside(false);
274
275 setTitle(R.string.permission_request_title);
276
277 mRequestedPermissions = getIntent().getStringArrayExtra(
278 PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
279 if (mRequestedPermissions == null) {
280 mRequestedPermissions = new String[0];
281 }
282
283 final int requestedPermCount = mRequestedPermissions.length;
284
285 if (requestedPermCount == 0) {
286 setResultAndFinish();
287 return;
288 }
289
290 PackageInfo callingPackageInfo = getCallingPackageInfo();
291
292 if (callingPackageInfo == null || callingPackageInfo.requestedPermissions == null
293 || callingPackageInfo.requestedPermissions.length <= 0) {
294 setResultAndFinish();
295 return;
296 }
297
298 // Don't allow legacy apps to request runtime permissions.
299 if (callingPackageInfo.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
300 // Returning empty arrays means a cancellation.
301 mRequestedPermissions = new String[0];
302 setResultAndFinish();
303 return;
304 }
305
306 mCallingUid = callingPackageInfo.applicationInfo.uid;
307
308 UserHandle userHandle = UserHandle.getUserHandleForUid(mCallingUid);
309
310 if (DeviceUtils.isTelevision(this)) {
311 mViewHandler = new com.android.packageinstaller.permission.ui.television
312 .GrantPermissionsViewHandlerImpl(this,
313 mCallingPackage).setResultListener(this);
314 } else if (DeviceUtils.isWear(this)) {
315 mViewHandler = new GrantPermissionsWatchViewHandler(this).setResultListener(this);
316 } else if (DeviceUtils.isAuto(this)) {
317 mViewHandler = new GrantPermissionsAutoViewHandler(this, mCallingPackage, userHandle)
318 .setResultListener(this);
319 } else {
320 mViewHandler = new com.android.packageinstaller.permission.ui.handheld
321 .GrantPermissionsViewHandlerImpl(this, mCallingPackage, userHandle)
322 .setResultListener(this);
323 }
324
325 mAppPermissions = new AppPermissions(this, callingPackageInfo, false,
326 new Runnable() {
327 @Override
328 public void run() {
329 setResultAndFinish();
330 }
331 });
332
333 for (String requestedPermission : mRequestedPermissions) {
334 if (requestedPermission == null) {
335 continue;
336 }
337
338 ArrayList<String> affectedPermissions =
339 computeAffectedPermissions(requestedPermission);
340
341 int numAffectedPermissions = affectedPermissions.size();
342 for (int i = 0; i < numAffectedPermissions; i++) {
343 AppPermissionGroup group =
344 mAppPermissions.getGroupForPermission(affectedPermissions.get(i));
345 if (group == null) {
346 reportRequestResult(affectedPermissions.get(i),
347 PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED);
348
349 continue;
350 }
351
352 addRequestedPermissions(group, affectedPermissions.get(i), icicle == null);
353 }
354 }
355
356 int numGroupStates = mRequestGrantPermissionGroups.size();
357 for (int groupStateNum = 0; groupStateNum < numGroupStates; groupStateNum++) {
358 GroupState groupState = mRequestGrantPermissionGroups.valueAt(groupStateNum);
359 AppPermissionGroup group = groupState.mGroup;
360
361 // Restore permission group state after lifecycle events
362 if (icicle != null) {
363 groupState.mState = icicle.getInt(
364 getInstanceStateKey(mRequestGrantPermissionGroups.keyAt(groupStateNum)),
365 groupState.mState);
366 }
367
368 // Do not attempt to grant background access if foreground access is not either already
369 // granted or requested
370 if (group.isBackgroundGroup()) {
371 // Check if a foreground permission is already granted
372 boolean foregroundGroupAlreadyGranted = mAppPermissions.getPermissionGroup(
373 group.getName()).areRuntimePermissionsGranted();
374 boolean hasForegroundRequest = (getForegroundGroupState(group.getName()) != null);
375
376 if (!foregroundGroupAlreadyGranted && !hasForegroundRequest) {
377 // The background permission cannot be granted at this time
378 int numPermissions = groupState.affectedPermissions.length;
379 for (int permissionNum = 0; permissionNum < numPermissions; permissionNum++) {
380 Log.w(LOG_TAG,
381 "Cannot grant " + groupState.affectedPermissions[permissionNum]
382 + " as the matching foreground permission is not already "
383 + "granted.");
384 }
385
386 groupState.mState = GroupState.STATE_SKIPPED;
387
388 reportRequestResult(groupState.affectedPermissions,
389 PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED);
390 }
391 }
392 }
393
394 setContentView(mViewHandler.createView());
395
396 Window window = getWindow();
397 WindowManager.LayoutParams layoutParams = window.getAttributes();
398 mViewHandler.updateWindowAttributes(layoutParams);
399 window.setAttributes(layoutParams);
400
401 // Restore UI state after lifecycle events. This has to be before
402 // showNextPermissionGroupGrantRequest is called. showNextPermissionGroupGrantRequest might
403 // update the UI and the UI behaves differently for updates and initial creations.
404 if (icicle != null) {
405 mViewHandler.loadInstanceState(icicle);
406 }
407
408 if (!showNextPermissionGroupGrantRequest()) {
409 setResultAndFinish();
410 }
411 }
396 Window window = getWindow();
397 WindowManager.LayoutParams layoutParams = window.getAttributes();
398 mViewHandler.updateWindowAttributes(layoutParams);
399 window.setAttributes(layoutParams);
弹出授权的dialog界面。
xref: /packages/apps/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
803 /**
804 * Grants or revoked the affected permissions for a single {@link groupState}.
805 *
806 * @param groupState The group state with the permissions to grant/revoke
807 * @param granted {@code true} if the permissions should be granted, {@code false} if they
808 * should be revoked
809 * @param doNotAskAgain if the permissions should be revoked should be app be allowed to ask
810 * again for the same permissions?
811 */
812 private void onPermissionGrantResultSingleState(GroupState groupState, boolean granted,
813 boolean doNotAskAgain) {
814 if (groupState != null && groupState.mGroup != null
815 && groupState.mState == GroupState.STATE_UNKNOWN) {
816 if (granted) {
817 groupState.mGroup.grantRuntimePermissions(doNotAskAgain,
818 groupState.affectedPermissions);
819 groupState.mState = GroupState.STATE_ALLOWED;
820
821 reportRequestResult(groupState.affectedPermissions,
822 PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED);
823 } else {
824 groupState.mGroup.revokeRuntimePermissions(doNotAskAgain,
825 groupState.affectedPermissions);
826 groupState.mState = GroupState.STATE_DENIED;
827
828 reportRequestResult(groupState.affectedPermissions, doNotAskAgain
829 ?
830 PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE
831 : PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED);
832 }
833 }
834 }
用户选择授权与否会在onPermissionGrantResultSingleState方法中处理。groupState.mGroup.grantRuntimePermissions方法最终会调用到AppPermissionGroup.java类中的grantRuntimePermissions方法。
xref: /packages/apps/PermissionController/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java
754 /**
755 * Grant permissions of the group.
756 *
757 * <p>This also automatically grants all app ops for permissions that have app ops.
758 * <p>This does <u>only</u> grant permissions in {@link #mPermissions}, i.e. usually not
759 * the background permissions.
760 *
761 * @param fixedByTheUser If the user requested that she/he does not want to be asked again
762 * @param filterPermissions If {@code null} all permissions of the group will be granted.
763 * Otherwise only permissions in {@code filterPermissions} will be
764 * granted.
765 *
766 * @return {@code true} iff all permissions of this group could be granted.
767 */
768 public boolean grantRuntimePermissions(boolean fixedByTheUser, String[] filterPermissions) {
769 boolean killApp = false;
770 boolean wasAllGranted = true;
771
772 // We toggle permissions only to apps that support runtime
773 // permissions, otherwise we toggle the app op corresponding
774 // to the permission if the permission is granted to the app.
775 for (Permission permission : mPermissions.values()) {
776 if (filterPermissions != null
777 && !ArrayUtils.contains(filterPermissions, permission.getName())) {
778 continue;
779 }
780
781 if (!permission.isGrantingAllowed(mIsEphemeralApp, mAppSupportsRuntimePermissions)) {
782 // Skip unallowed permissions.
783 continue;
784 }
785
786 boolean wasGranted = permission.isGrantedIncludingAppOp();
787
788 if (mAppSupportsRuntimePermissions) {
789 // Do not touch permissions fixed by the system.
790 if (permission.isSystemFixed()) {
791 wasAllGranted = false;
792 break;
793 }
794
795 // Ensure the permission app op enabled before the permission grant.
796 if (permission.affectsAppOp() && !permission.isAppOpAllowed()) {
797 permission.setAppOpAllowed(true);
798 }
799
800 // Grant the permission if needed.
801 if (!permission.isGranted()) {
802 permission.setGranted(true);
803 }
804
805 // Update the permission flags.
806 if (!fixedByTheUser) {
807 // Now the apps can ask for the permission as the user
808 // no longer has it fixed in a denied state.
809 if (permission.isUserFixed() || permission.isUserSet()) {
810 permission.setUserFixed(false);
811 permission.setUserSet(false);
812 }
813 }
814 } else {
815 // Legacy apps cannot have a not granted permission but just in case.
816 if (!permission.isGranted()) {
817 continue;
818 }
819
820 // If the permissions has no corresponding app op, then it is a
821 // third-party one and we do not offer toggling of such permissions.
822 if (permission.affectsAppOp()) {
823 if (!permission.isAppOpAllowed()) {
824 permission.setAppOpAllowed(true);
825
826 // Legacy apps do not know that they have to retry access to a
827 // resource due to changes in runtime permissions (app ops in this
828 // case). Therefore, we restart them on app op change, so they
829 // can pick up the change.
830 killApp = true;
831 }
832
833 // Mark that the permission should not be be granted on upgrade
834 // when the app begins supporting runtime permissions.
835 if (permission.shouldRevokeOnUpgrade()) {
836 permission.setRevokeOnUpgrade(false);
837 }
838 }
839
840 // Granting a permission explicitly means the user already
841 // reviewed it so clear the review flag on every grant.
842 if (permission.isReviewRequired()) {
843 permission.unsetReviewRequired();
844 }
845 }
846
847 // If we newly grant background access to the fine location, double-guess the user some
848 // time later if this was really the right choice.
849 if (!wasGranted && permission.isGrantedIncludingAppOp()) {
850 if (permission.getName().equals(ACCESS_FINE_LOCATION)) {
851 Permission bgPerm = permission.getBackgroundPermission();
852 if (bgPerm != null) {
853 if (bgPerm.isGrantedIncludingAppOp()) {
854 mTriggerLocationAccessCheckOnPersist = true;
855 }
856 }
857 } else if (permission.getName().equals(ACCESS_BACKGROUND_LOCATION)) {
858 ArrayList<Permission> fgPerms = permission.getForegroundPermissions();
859 if (fgPerms != null) {
860 int numFgPerms = fgPerms.size();
861 for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
862 Permission fgPerm = fgPerms.get(fgPermNum);
863
864 if (fgPerm.getName().equals(ACCESS_FINE_LOCATION)) {
865 if (fgPerm.isGrantedIncludingAppOp()) {
866 mTriggerLocationAccessCheckOnPersist = true;
867 }
868
869 break;
870 }
871 }
872 }
873 }
874 }
875 }
876
877 if (!mDelayChanges) {
878 persistChanges(false);
879
880 if (killApp) {
881 killApp(KILL_REASON_APP_OP_CHANGE);
882 }
883 }
884
885 return wasAllGranted;
886 }
如果不延迟改变就调用persistChanges方法。
xref: /packages/apps/PermissionController/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java
1214 /**
1215 * If the changes to this group were delayed, persist them to the platform.
1216 *
1217 * @param mayKillBecauseOfAppOpsChange If the app these permissions belong to may be killed if
1218 * app ops change. If this is set to {@code false} the
1219 * caller has to make sure to kill the app if needed.
1220 */
1221 void persistChanges(boolean mayKillBecauseOfAppOpsChange) {
1222 int uid = mPackageInfo.applicationInfo.uid;
1223
1224 int numPermissions = mPermissions.size();
1225 boolean shouldKillApp = false;
1226
1227 for (int i = 0; i < numPermissions; i++) {
1228 Permission permission = mPermissions.valueAt(i);
1229
1230 if (!permission.isSystemFixed()) {
1231 if (permission.isGranted()) {
1232 mPackageManager.grantRuntimePermission(mPackageInfo.packageName,
1233 permission.getName(), mUserHandle);
1234 } else {
1235 boolean isCurrentlyGranted = mContext.checkPermission(permission.getName(), -1,
1236 uid) == PERMISSION_GRANTED;
1237
1238 if (isCurrentlyGranted) {
1239 mPackageManager.revokeRuntimePermission(mPackageInfo.packageName,
1240 permission.getName(), mUserHandle);
1241 }
1242 }
1243 }
1244
1245 int flags = (permission.isUserSet() ? PackageManager.FLAG_PERMISSION_USER_SET : 0)
1246 | (permission.isUserFixed() ? PackageManager.FLAG_PERMISSION_USER_FIXED : 0)
1247 | (permission.shouldRevokeOnUpgrade()
1248 ? PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE : 0)
1249 | (permission.isPolicyFixed() ? PackageManager.FLAG_PERMISSION_POLICY_FIXED : 0)
1250 | (permission.isReviewRequired()
1251 ? PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED : 0);
1252
1253 mPackageManager.updatePermissionFlags(permission.getName(),
1254 mPackageInfo.packageName,
1255 PackageManager.FLAG_PERMISSION_USER_SET
1256 | PackageManager.FLAG_PERMISSION_USER_FIXED
1257 | PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE
1258 | PackageManager.FLAG_PERMISSION_POLICY_FIXED
1259 | PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED,
1260 flags, mUserHandle);
1261
1262 if (permission.affectsAppOp()) {
1263 if (!permission.isSystemFixed()) {
1264 // Enabling/Disabling an app op may put the app in a situation in which it has
1265 // a handle to state it shouldn't have, so we have to kill the app. This matches
1266 // the revoke runtime permission behavior.
1267 if (permission.isAppOpAllowed()) {
1268 shouldKillApp |= allowAppOp(permission, uid);
1269 } else {
1270 shouldKillApp |= disallowAppOp(permission, uid);
1271 }
1272 }
1273 }
1274 }
1275
1276 if (mayKillBecauseOfAppOpsChange && shouldKillApp) {
1277 killApp(KILL_REASON_APP_OP_CHANGE);
1278 }
1279
1280 if (mTriggerLocationAccessCheckOnPersist) {
1281 new LocationAccessCheck(mContext, null).checkLocationAccessSoon();
1282 mTriggerLocationAccessCheckOnPersist = false;
1283 }
1284 }
mPackageManager.grantRuntimePermission;调用PackageManager的grantRuntimePermission。PackageManager是抽象类需要调用它的实现类ApplicationPackageManager里面的grantRuntimePermission方法,然后通过AIDL跨进程通信调用到PackageManagerService.java类中的grantRuntimePermission。
xref: /frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
5721 @Override
5722 public void grantRuntimePermission(String packageName, String permName, final int userId) {
5723 boolean overridePolicy = (checkUidPermission(
5724 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
5725 == PackageManager.PERMISSION_GRANTED);
5726
5727 mPermissionManager.grantRuntimePermission(permName, packageName, overridePolicy,
5728 getCallingUid(), userId, mPermissionCallback);
5729 }
调用PermissionManager类的grantRuntimePermission方法,最终会调用到PermissionManagerService类中的grantRuntimePermission方法。
xref: /frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
2083 private void grantRuntimePermission(String permName, String packageName, boolean overridePolicy,
2084 int callingUid, final int userId, PermissionCallback callback) {
2085 if (!mUserManagerInt.exists(userId)) {
2086 Log.e(TAG, "No such user:" + userId);
2087 return;
2088 }
2089
2090 mContext.enforceCallingOrSelfPermission(
2091 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
2092 "grantRuntimePermission");
2093
2094 enforceCrossUserPermission(callingUid, userId,
2095 true, // requireFullPermission
2096 true, // checkShell
2097 false, // requirePermissionWhenSameUser
2098 "grantRuntimePermission");
2099
2100 final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
2101 if (pkg == null || pkg.mExtras == null) {
2102 throw new IllegalArgumentException("Unknown package: " + packageName);
2103 }
2104 final BasePermission bp;
2105 synchronized(mLock) {
2106 bp = mSettings.getPermissionLocked(permName);
2107 }
2108 if (bp == null) {
2109 throw new IllegalArgumentException("Unknown permission: " + permName);
2110 }
2111 if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
2112 throw new IllegalArgumentException("Unknown package: " + packageName);
2113 }
2114
2115 bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
2116
2117 // If a permission review is required for legacy apps we represent
2118 // their permissions as always granted runtime ones since we need
2119 // to keep the review required permission flag per user while an
2120 // install permission's state is shared across all users.
2121 if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
2122 && bp.isRuntime()) {
2123 return;
2124 }
2125
2126 final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
2127
2128 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2129 final PermissionsState permissionsState = ps.getPermissionsState();
2130
2131 final int flags = permissionsState.getPermissionFlags(permName, userId);
2132 if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
2133 Log.e(TAG, "Cannot grant system fixed permission "
2134 + permName + " for package " + packageName);
2135 return;
2136 }
2137 if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
2138 Log.e(TAG, "Cannot grant policy fixed permission "
2139 + permName + " for package " + packageName);
2140 return;
2141 }
2142
2143 if (bp.isHardRestricted()
2144 && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
2145 Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
2146 + permName + " for package " + packageName);
2147 return;
2148 }
2149
2150 if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
2151 pkg.applicationInfo, UserHandle.of(userId), permName).canBeGranted()) {
2152 Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
2153 + packageName);
2154 return;
2155 }
2156
2157 if (bp.isDevelopment()) {
2158 // Development permissions must be handled specially, since they are not
2159 // normal runtime permissions. For now they apply to all users.
2160 if (permissionsState.grantInstallPermission(bp) !=
2161 PERMISSION_OPERATION_FAILURE) {
2162 if (callback != null) {
2163 callback.onInstallPermissionGranted();
2164 }
2165 }
2166 return;
2167 }
2168
2169 if (ps.getInstantApp(userId) && !bp.isInstant()) {
2170 throw new SecurityException("Cannot grant non-ephemeral permission"
2171 + permName + " for package " + packageName);
2172 }
2173
2174 if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
2175 Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
2176 return;
2177 }
2178
2179 final int result = permissionsState.grantRuntimePermission(bp, userId);
2180 switch (result) {
2181 case PERMISSION_OPERATION_FAILURE: {
2182 return;
2183 }
2184
2185 case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
2186 if (callback != null) {
2187 callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId);
2188 }
2189 }
2190 break;
2191 }
2192
2193 if (bp.isRuntime()) {
2194 logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
2195 }
2196
2197 if (callback != null) {
2198 callback.onPermissionGranted(uid, userId);
2199 }
2200
2201 if (bp.isRuntime()) {
2202 notifyRuntimePermissionStateChanged(packageName, userId);
2203 }
2204
2205 // Only need to do this if user is initialized. Otherwise it's a new user
2206 // and there are no processes running as the user yet and there's no need
2207 // to make an expensive call to remount processes for the changed permissions.
2208 if (READ_EXTERNAL_STORAGE.equals(permName)
2209 || WRITE_EXTERNAL_STORAGE.equals(permName)) {
2210 final long token = Binder.clearCallingIdentity();
2211 try {
2212 if (mUserManagerInt.isUserInitialized(userId)) {
2213 StorageManagerInternal storageManagerInternal = LocalServices.getService(
2214 StorageManagerInternal.class);
2215 storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
2216 }
2217 } finally {
2218 Binder.restoreCallingIdentity(token);
2219 }
2220 }
2221
2222 }
2197 if (callback != null) {
2198 callback.onPermissionGranted(uid, userId);
2199 }
通过callback将处理结果回调给PackageManagerService。
xref: /frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
1758 private PermissionCallback mPermissionCallback = new PermissionCallback() {
1759 @Override
1760 public void onGidsChanged(int appId, int userId) {
1761 mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
1762 }
1763 @Override
1764 public void onPermissionGranted(int uid, int userId) {
1765 mOnPermissionChangeListeners.onPermissionsChanged(uid);
1766
1767 // Not critical; if this is lost, the application has to request again.
1768 synchronized (mPackages) {
1769 mSettings.writeRuntimePermissionsForUserLPr(userId, false);
1770 }
1771 }
1772 @Override
1773 public void onInstallPermissionGranted() {
1774 synchronized (mPackages) {
1775 scheduleWriteSettingsLocked();
1776 }
1777 }
1778 @Override
1779 public void onPermissionRevoked(int uid, int userId) {
1780 mOnPermissionChangeListeners.onPermissionsChanged(uid);
1781
1782 synchronized (mPackages) {
1783 // Critical; after this call the application should never have the permission
1784 mSettings.writeRuntimePermissionsForUserLPr(userId, true);
1785 }
1786
1787 final int appId = UserHandle.getAppId(uid);
1788 killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
1789 }
1790 @Override
1791 public void onInstallPermissionRevoked() {
1792 synchronized (mPackages) {
1793 scheduleWriteSettingsLocked();
1794 }
1795 }
1796 @Override
1797 public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
1798 synchronized (mPackages) {
1799 for (int userId : updatedUserIds) {
1800 mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
1801 }
1802 }
1803 }
1804 @Override
1805 public void onInstallPermissionUpdated() {
1806 synchronized (mPackages) {
1807 scheduleWriteSettingsLocked();
1808 }
1809 }
1810 @Override
1811 public void onPermissionRemoved() {
1812 synchronized (mPackages) {
1813 mSettings.writeLPr();
1814 }
1815 }
1816 };
mOnPermissionChangeListeners.onPermissionsChanged(uid);将处理结果回调给用户。mSettings.writeRuntimePermissionsForUserLPr(userId, false);把修改权限的结果写到runtime-permissions.xml文件里面
xref: /frameworks/base/services/core/java/com/android/server/pm/Settings.java
5200 private void writePermissionsSync(int userId) {
5201 AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId),
5202 "package-perms-" + userId);
5203
5204 ArrayMap<String, List<PermissionState>> permissionsForPackage = new ArrayMap<>();
5205 ArrayMap<String, List<PermissionState>> permissionsForSharedUser = new ArrayMap<>();
5206
5207 synchronized (mPersistenceLock) {
5208 mWriteScheduled.delete(userId);
5209
5210 final int packageCount = mPackages.size();
5211 for (int i = 0; i < packageCount; i++) {
5212 String packageName = mPackages.keyAt(i);
5213 PackageSetting packageSetting = mPackages.valueAt(i);
5214 if (packageSetting.sharedUser == null) {
5215 PermissionsState permissionsState = packageSetting.getPermissionsState();
5216 List<PermissionState> permissionsStates = permissionsState
5217 .getRuntimePermissionStates(userId);
5218 if (!permissionsStates.isEmpty()) {
5219 permissionsForPackage.put(packageName, permissionsStates);
5220 }
5221 }
5222 }
5223
5224 final int sharedUserCount = mSharedUsers.size();
5225 for (int i = 0; i < sharedUserCount; i++) {
5226 String sharedUserName = mSharedUsers.keyAt(i);
5227 SharedUserSetting sharedUser = mSharedUsers.valueAt(i);
5228 PermissionsState permissionsState = sharedUser.getPermissionsState();
5229 List<PermissionState> permissionsStates = permissionsState
5230 .getRuntimePermissionStates(userId);
5231 if (!permissionsStates.isEmpty()) {
5232 permissionsForSharedUser.put(sharedUserName, permissionsStates);
5233 }
5234 }
5235 }
5236
5237 FileOutputStream out = null;
5238 try {
5239 out = destination.startWrite();
5240
5241 XmlSerializer serializer = Xml.newSerializer();
5242 serializer.setOutput(out, StandardCharsets.UTF_8.name());
5243 serializer.setFeature(
5244 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
5245 serializer.startDocument(null, true);
5246
5247 serializer.startTag(null, TAG_RUNTIME_PERMISSIONS);
5248
5249 final int version = mVersions.get(userId, INITIAL_VERSION);
5250 serializer.attribute(null, ATTR_VERSION, Integer.toString(version));
5251
5252 String fingerprint = mFingerprints.get(userId);
5253 if (fingerprint != null) {
5254 serializer.attribute(null, ATTR_FINGERPRINT, fingerprint);
5255 }
5256
5257 final int packageCount = permissionsForPackage.size();
5258 for (int i = 0; i < packageCount; i++) {
5259 String packageName = permissionsForPackage.keyAt(i);
5260 List<PermissionState> permissionStates = permissionsForPackage.valueAt(i);
5261 serializer.startTag(null, TAG_PACKAGE);
5262 serializer.attribute(null, ATTR_NAME, packageName);
5263 writePermissions(serializer, permissionStates);
5264 serializer.endTag(null, TAG_PACKAGE);
5265 }
5266
5267 final int sharedUserCount = permissionsForSharedUser.size();
5268 for (int i = 0; i < sharedUserCount; i++) {
5269 String packageName = permissionsForSharedUser.keyAt(i);
5270 List<PermissionState> permissionStates = permissionsForSharedUser.valueAt(i);
5271 serializer.startTag(null, TAG_SHARED_USER);
5272 serializer.attribute(null, ATTR_NAME, packageName);
5273 writePermissions(serializer, permissionStates);
5274 serializer.endTag(null, TAG_SHARED_USER);
5275 }
5276
5277 serializer.endTag(null, TAG_RUNTIME_PERMISSIONS);
5278
5279 serializer.endDocument();
5280 destination.finishWrite(out);
5281
5282 if (Build.FINGERPRINT.equals(fingerprint)) {
5283 mDefaultPermissionsGranted.put(userId, true);
5284 }
5285 // Any error while writing is fatal.
5286 } catch (Throwable t) {
5287 Slog.wtf(PackageManagerService.TAG,
5288 "Failed to write settings, restoring backup", t);
5289 destination.failWrite(out);
5290 } finally {
5291 IoUtils.closeQuietly(out);
5292 }
5293 }