[TOC]
0 综述 基于 Android 7.1.1 源码,分析系统的权限管理机制!
本片文章总结一下权限授予的相关接口。
对于 dangrous 权限,应用程序需要显式的弹出弹窗,让用户主动的选择。当用户撤销或者授予时,会主动的调用!
但是对于 normal permission,siginature permission 以及 uri permission 都是无需弹窗申请的!
那么我们来看下系统中有那些和其相关的接口!
1 grantPermission - ContextImpl 在 ContextImpl 中提供了一个 grantUriPermission 方法:
1.1 grantUriPermission 该方法由于是在 ContextImpl 暴露的,所以应用程序可以通过该方法 grant uri permission 给其他应用程序:
1 2 3 4 5 6 7 8 9 10 11 @Override public void grantUriPermission (String toPackage, Uri uri, int modeFlags) { try { ActivityManagerNative.getDefault().grantUriPermission( mMainThread.getApplicationThread(), toPackage, ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
不多说了!
2 grantPermission - ActivityManagerService ActivityManagerService 内部提供了一些和 uri permission 相关的接口:
2.1 grantUriPermission 授予一个 uri permisson 给 target package,这个方法授予的 permission 是一个 global permisson;
因为其在调用 grantUriPermissionLocked 时传入的 UriPermissionOwner owner 为 null;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Override public void grantUriPermission (IApplicationThread caller, String targetPkg, Uri uri, final int modeFlags, int userId) { enforceNotIsolatedCaller("grantUriPermission" ); GrantUri grantUri = new GrantUri(userId, uri, false ); synchronized (this ) { final ProcessRecord r = getRecordForAppLocked(caller); if (r == null ) { throw new SecurityException("Unable to find app for caller " + caller + " when granting permission to uri " + grantUri); } if (targetPkg == null ) { throw new IllegalArgumentException("null target" ); } if (grantUri == null ) { throw new IllegalArgumentException("null uri" ); } Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); grantUriPermissionLocked(r.uid, targetPkg, grantUri, modeFlags, null , UserHandle.getUserId(r.uid)); } }
2.1.1 new GrantUri GrantUri 实例是对 uri 信息的简单封装:
1 2 3 4 5 6 7 8 9 10 public static class GrantUri { public final int sourceUserId; public final Uri uri; public boolean prefix; public GrantUri (int sourceUserId, Uri uri, boolean prefix) { this .sourceUserId = sourceUserId; this .uri = uri; this .prefix = prefix; }
2.1.2 跨进程调用 ContextImpl 的 grantUriPermission 可以跨进程调用该方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public void grantUriPermission (IApplicationThread caller, String targetPkg, Uri uri, int mode, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller.asBinder()); data.writeString(targetPkg); uri.writeToParcel(data, 0 ); data.writeInt(mode); data.writeInt(userId); mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0 ); reply.readException(); data.recycle(); reply.recycle(); }
1 2 3 4 5 6 7 8 9 10 11 12 case GRANT_URI_PERMISSION_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); String targetPkg = data.readString(); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); int userId = data.readInt(); grantUriPermission(app, targetPkg, uri, mode, userId); reply.writeNoException(); return true ; }
2.2 grantUriPermissionLocked - 内部调用 该方法的特点是,系统在调用时,会持有 AMS 大锁,所以此时系统进程的其他需要 AMS 大锁的线程会等待:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void grantUriPermissionLocked (int callingUid, String targetPkg, GrantUri grantUri, final int modeFlags, UriPermissionOwner owner, int targetUserId) { if (targetPkg == null ) { throw new NullPointerException("targetPkg" ); } int targetUid; final IPackageManager pm = AppGlobals.getPackageManager(); try { targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING, targetUserId); } catch (RemoteException ex) { return ; } targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, modeFlags, targetUid); if (targetUid < 0 ) { return ; } grantUriPermissionUncheckedLocked(targetUid, targetPkg, grantUri, modeFlags, owner); }
这里调用了 checkGrantUriPermissionLocked 方法,检查是否需要授予 uri 权限!
checkGrantUriPermissionLocked 方法会判断是否已经有 uri 权限,以及发送包含 uri 的 intent 程序是否有权限访问 uri 等等!!
只有发送方对 uri 有权限,接收者才能被授予权限!!
2.2.1 调用时机
第二个是在 1.1 grantUriPermission 中调用的;
第二个是在 1.6 grantUriPermissionFromOwner 中调用的;
该方法也是一个内部方法!
2.3 grantUriPermissionUncheckedLocked - 内部调用,核心接口 这个方法不会做一些 check 操作,所以最好不要直接调用,默认发送方对 uri 是有权限的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void grantUriPermissionUncheckedLocked (int targetUid, String targetPkg, GrantUri grantUri, final int modeFlags, UriPermissionOwner owner) { if (!Intent.isAccessUriMode(modeFlags)) { return ; } if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri); final String authority = grantUri.uri.getAuthority(); final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId, MATCH_DEBUG_TRIAGED_MISSING); if (pi == null ) { Slog.w(TAG, "No content provider found for grant: " + grantUri.toSafeString()); return ; } if ((modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0 ) { grantUri.prefix = true ; } final UriPermission perm = findOrCreateUriPermissionLocked( pi.packageName, targetPkg, targetUid, grantUri); perm.grantModes(modeFlags, owner); }
所以我们看到,对于 uri permission,其管理是在 AMS 中的!
2.3.1 findOrCreateUriPermissionLocked 找到一个已存在或者新建的 UriPermission 实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private UriPermission findOrCreateUriPermissionLocked (String sourcePkg, String targetPkg, int targetUid, GrantUri grantUri) { ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); if (targetUris == null ) { targetUris = Maps.newArrayMap(); mGrantedUriPermissions.put(targetUid, targetUris); } UriPermission perm = targetUris.get(grantUri); if (perm == null ) { perm = new UriPermission(sourcePkg, targetPkg, targetUid, grantUri); targetUris.put(grantUri, perm); } return perm; }
在 ActivityManagerService 内部是有一个 mGrantedUriPermissions 数组:
1 2 3 @GuardedBy ("this" ) mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>();
SparseArray 的下标是被授予 uri permission 的目标 uid,值是一个 ArrayMap<GrantUri, UriPermission>,保存了 uri 和对应的 UriPermission 的映射关系!
2.3.1.1 new UriPermission 创建一个更新的 UriPermission:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 final class UriPermission { private static final String TAG = "UriPermission" ; public static final int STRENGTH_NONE = 0 ; public static final int STRENGTH_OWNED = 1 ; public static final int STRENGTH_GLOBAL = 2 ; public static final int STRENGTH_PERSISTABLE = 3 ; final int targetUserId; final String sourcePkg; final String targetPkg; final int targetUid; final GrantUri uri; int modeFlags = 0 ; int ownedModeFlags = 0 ; int globalModeFlags = 0 ; int persistableModeFlags = 0 ; int persistedModeFlags = 0 ; long persistedCreateTime = INVALID_TIME; private static final long INVALID_TIME = Long.MIN_VALUE; private ArraySet<UriPermissionOwner> mReadOwners; private ArraySet<UriPermissionOwner> mWriteOwners; private String stringName; UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) { this .targetUserId = UserHandle.getUserId(targetUid); this .sourcePkg = sourcePkg; this .targetPkg = targetPkg; this .targetUid = targetUid; this .uri = uri; } ... ... ... ... }
上面只是简单的介绍了下 UriPermission 内部的一些主要的属性,后面我们遇到了具体的逻辑时再分析!
2.3.2 UriPermission.grantModes 授予 uri permission:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 void grantModes (int modeFlags, UriPermissionOwner owner) { final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0 ; modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); if (persistable) { persistableModeFlags |= modeFlags; } if (owner == null ) { globalModeFlags |= modeFlags; } else { if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 ) { addReadOwner(owner); } if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 ) { addWriteOwner(owner); } } updateModeFlags (); }
首先,判断是否需要 persist,同时对传入的 modeFlags 作如下处理:1 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
只保留 modeFlags 中的这两位,也就是说,此时,modeFlags 要么择其一,要么二者都有;
如果 modeFlags 需要 persistable,那么设置 persistableModeFlags;
接着,判断是否指定 UriPermissionOwner:
如果没有,那么该权限就是 global 的,更新 globalModeFlags 标志位;
如果有,说明这是一个有指定 owner 的权限,那就添加到如下集合中:
1 2 private ArraySet<UriPermissionOwner> mReadOwners; private ArraySet<UriPermissionOwner> mWriteOwners;
同时,更新 ownedModeFlags 的标志位(只有在初始化的 mReadOwners 和 mWriteOwners,第一次添加 owner 时)
最后,调用 updateModeFlags 更新 modeFlags
其实整个过程就是对传入的 modeFlags 的标志位进行一一拆解,然后保存到 ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags 中,最后在 updateModeFlags 中,用这几个标志位更新 modeFlags;
2.3.2.1 addReadOwner UriPermission 内部方法,,用于添加一个对该 uri 有非全局,读权限的拥有者;1 2 3 4 5 6 7 8 9 10 11 12 13 14 private void addReadOwner (UriPermissionOwner owner) { if (mReadOwners == null ) { mReadOwners = Sets.newArraySet(); ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION; updateModeFlags(); } if (mReadOwners.add(owner)) { owner.addReadPermission(this ); } }
因为 mReadOwners 默认为 null,所以如果有最开始要初始化 mReadOwners,我们可以看到:
只有在第一次初始化 mReadOwners 时,才会设置 ownedModeFlags 标志位;
以后在添加新的 owner 时,就不在处理了!
2.3.2.2 addWriteOwner UriPermission 内部方法,用于添加一个对该 uri 有非全局,写权限的拥有者;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private void addWriteOwner (UriPermissionOwner owner) { if (mWriteOwners == null ) { mWriteOwners = Sets.newArraySet(); ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; updateModeFlags(); } if (mWriteOwners.add(owner)) { owner.addWritePermission(this ); } }
因为 mWriteOwners 默认为 null,所以如果有最开始要初始化 mWriteOwners,我们可以看到:
只有在第一次初始化 mWriteOwners 时,才会设置 ownedModeFlags 标志位;
以后在添加新的 owner 时,就不在处理了!
2.3.2.3 updateModeFlags UriPermission 内部方法,更新 modeFlags 标志位;
1 2 3 4 5 6 7 8 9 10 11 12 13 private void updateModeFlags () { final int oldModeFlags = modeFlags; modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags; if (Log.isLoggable(TAG, Log.VERBOSE) && (modeFlags != oldModeFlags)) { Slog.d(TAG, "Permission for " + targetPkg + " to " + uri + " is changing from 0x" + Integer.toHexString(oldModeFlags) + " to 0x" + Integer.toHexString(modeFlags), new Throwable()); } }
不多说了!
2.3.3 调用时机
第二个是在 1.2 grantUriPermissionLocked 中调用的;
第二个是在 1.5 grantUriPermissionUncheckedFromIntentLocked 中调用的;
可以看出,均是内部调用,因为该方法不做 check 所以,不建议直接调用;
2.4 grantUriPermissionFromIntentLocked 通过 intent 授予 targetPkg uri permission,该方法会先去 check 看是否需要授予权限:
1 2 3 4 5 6 7 8 9 10 11 12 void grantUriPermissionFromIntentLocked (int callingUid, String targetPkg, Intent intent, UriPermissionOwner owner, int targetUserId) { NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent, intent != null ? intent.getFlags() : 0 , null , targetUserId); if (needed == null ) { return ; } grantUriPermissionUncheckedFromIntentLocked(needed, owner); }
2.4.1 调用时机 我们来看下该方法的调用时机,框架中主要的调用均是在和 activity 启动,finish,已经结果返回相关的地方:
2.4.1.1 finishActivityResultsLocked - ActivityStack 在退出一个 activity 的时候,如果我们要返回结果给启动者 activity 的时候:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 final void finishActivityResultsLocked (ActivityRecord r, int resultCode, Intent resultData) { ActivityRecord resultTo = r.resultTo; if (resultTo != null ) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo + " who=" + r.resultWho + " req=" + r.requestCode + " res=" + resultCode + " data=" + resultData); if (resultTo.userId != r.userId) { if (resultData != null ) { resultData.prepareToLeaveUser(r.userId); } } if (r.info.applicationInfo.uid > 0 ) { mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, resultTo.packageName, resultData, resultTo.getUriPermissionsLocked(), resultTo.userId); } resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData); r.resultTo = null ; } else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r); r.results = null ; r.pendingResults = null ; r.newIntents = null ; r.icicle = null ; }
2.4.1.2 sendActivityResultLocked - ActivityStack 发送启动返回结果给 activity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void sendActivityResultLocked (int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data) { if (callingUid > 0 ) { mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, data, r.getUriPermissionsLocked(), r.userId); } if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r + " : who=" + resultWho + " req=" + requestCode + " res=" + resultCode + " data=" + data); if (mResumedActivity == r && r.app != null && r.app.thread != null ) { try { ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); list.add(new ResultInfo(resultWho, requestCode, resultCode, data)); r.app.thread.scheduleSendResult(r.appToken, list); return ; } catch (Exception e) { Slog.w(TAG, "Exception thrown sending result to " + r, e); } } r.addResultLocked(null , resultWho, requestCode, resultCode, data); }
不多说了!
2.4.1.3 deliverNewIntentLocked - ActivityRecord 该方法会拉起一个 activity 的 onNewIntent 方法:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 final void deliverNewIntentLocked (int callingUid, Intent intent, String referrer) { service.grantUriPermissionFromIntentLocked(callingUid, packageName, intent, getUriPermissionsLocked(), userId); final ReferrerIntent rintent = new ReferrerIntent(intent, referrer); boolean unsent = true ; final ActivityStack stack = task.stack; final boolean isTopActivityInStack = stack != null && stack.topRunningActivityLocked() == this ; final boolean isTopActivityWhileSleeping = service.isSleepingLocked() && isTopActivityInStack; if ((state == ActivityState.RESUMED || state == ActivityState.PAUSED || isTopActivityWhileSleeping) && app != null && app.thread != null ) { try { ArrayList<ReferrerIntent> ar = new ArrayList<>(1 ); ar.add(rintent); app.thread.scheduleNewIntent( ar, appToken, state == ActivityState.PAUSED ); unsent = false ; } catch (RemoteException e) { Slog.w(TAG, "Exception thrown sending new intent to " + this , e); } catch (NullPointerException e) { Slog.w(TAG, "Exception thrown sending new intent to " + this , e); } } if (unsent) { addNewIntentLocked(rintent); } }
2.4.1.3.1 getUriPermissionsLocked 同样的,ActivityRecord 内部也有一个 getUriPermissionsLocked 方法,用来获得其对应的 UriPermissionOwner 实例:
1 2 3 4 5 6 7 UriPermissionOwner getUriPermissionsLocked () { if (uriPermissions == null ) { uriPermissions = new UriPermissionOwner(service, this ); } return uriPermissions; }
2.4.1.4 startActivityUnchecked - ActivityStarter 在启动一个新的 acitivity 的时候:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private int startActivityUnchecked (final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor); computeLaunchingTaskFlags(); computeSourceStack(); mIntent.setFlags(mLaunchFlags); mReusedActivity = getReusableIntentActivity(); final int preferredLaunchStackId = (mOptions != null ) ? mOptions.getLaunchStackId() : INVALID_STACK_ID; ... ... ... mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId); ... ... ... return START_SUCCESS; }
不多说了!
2.5 grantUriPermissionUncheckedFromIntentLocked 通过 intent 授予 uri permission,但是该方法不会 check 是否需要授予权限,所以尽量不要直接调用这个函数;
1 2 3 4 5 6 7 8 9 10 11 void grantUriPermissionUncheckedFromIntentLocked (NeededUriGrants needed, UriPermissionOwner owner) { if (needed != null ) { for (int i=0 ; i<needed.size(); i++) { GrantUri grantUri = needed.get(i); grantUriPermissionUncheckedLocked(needed.targetUid, needed.targetPkg, grantUri, needed.flags, owner); } } }
首先遍历所有的 GrantUri,处理每一个 GrantUri 的授予!
2.5.1 调用时机 2.5.1.1 sendServiceArgsLocked 在我们启动 Service 的时候,我们会将启动参数 StartItems 发送给 Service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 private final void sendServiceArgsLocked (ServiceRecord r, boolean execInFg, boolean oomAdjusted) throws TransactionTooLargeException { final int N = r.pendingStarts.size(); if (N == 0 ) { return ; } while (r.pendingStarts.size() > 0 ) { Exception caughtException = null ; ServiceRecord.StartItem si = null ; try { si = r.pendingStarts.remove(0 ); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Sending arguments to: " + r + " " + r.intent + " args=" + si.intent); if (si.intent == null && N > 1 ) { continue ; } si.deliveredTime = SystemClock.uptimeMillis(); r.deliveredStarts.add(si); si.deliveryCount++; if (si.neededGrants != null ) { mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants, si.getUriPermissionsLocked()); } bumpServiceExecutingLocked(r, execInFg, "start" ); if (!oomAdjusted) { oomAdjusted = true ; mAm.updateOomAdjLocked(r.app); } int flags = 0 ; if (si.deliveryCount > 1 ) { flags |= Service.START_FLAG_RETRY; } if (si.doneExecutingCount > 0 ) { flags |= Service.START_FLAG_REDELIVERY; } r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent); } catch (TransactionTooLargeException e) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large: intent=" + si.intent); caughtException = e; } catch (RemoteException e) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r); caughtException = e; } catch (Exception e) { Slog.w(TAG, "Unexpected exception" , e); caughtException = e; } ... ... ... ... } }
逻辑很简单,不多说了!
2.5.1.2 StartItem.getUriPermissionsLocked 1 2 3 4 5 6 7 UriPermissionOwner getUriPermissionsLocked () { if (uriPermissions == null ) { uriPermissions = new UriPermissionOwner(sr.ams, this ); } return uriPermissions; }
2.6 grantUriPermissionFromOwner 授予 UriPermissionOwner owner 访问 uri 的 permission,这里的 UriPermissionOwner 是通过 IBinder token 转换而来!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Override public void grantUriPermissionFromOwner (IBinder token, int fromUid, String targetPkg, Uri uri, final int modeFlags, int sourceUserId, int targetUserId) { targetUserId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), targetUserId, false , ALLOW_FULL_ONLY, "grantUriPermissionFromOwner" , null ); synchronized (this ) { UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); if (owner == null ) { throw new IllegalArgumentException("Unknown owner: " + token); } if (fromUid != Binder.getCallingUid()) { if (Binder.getCallingUid() != Process.myUid()) { throw new SecurityException("nice try" ); } } if (targetPkg == null ) { throw new IllegalArgumentException("null target" ); } if (uri == null ) { throw new IllegalArgumentException("null uri" ); } grantUriPermissionLocked(fromUid, targetPkg, new GrantUri(sourceUserId, uri, false ), modeFlags, owner, targetUserId); } }
可以看到,grantUriPermissionFromOwner 可以提供跨进程的支持,也就是说应用程序可以通过 grantUriPermissionFromOwner 来授予其他应用 uri 权限;
同时,我们还看到要调用该方法,必须要存在一个 UriPermissionOwner,我们去看下如何创建一个 UriPermissionOwner:
2.6.1 newUriPermissionOwner 同样的,AMS 提供了一个 newUriPermissionOwner 方法,来实现创建一个新的 UriPermissionOwner,其支持跨进程调用:
1 2 3 4 5 6 7 8 9 10 @Override public IBinder newUriPermissionOwner (String name) { enforceNotIsolatedCaller("newUriPermissionOwner" ); synchronized (this ) { UriPermissionOwner owner = new UriPermissionOwner(this , name); return owner.getExternalTokenLocked(); } }
2.6.1.1 new UriPermissionOwner 新建一个 UriPermissionOwner 实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 final class UriPermissionOwner { final ActivityManagerService service; final Object owner; Binder externalToken; private ArraySet<UriPermission> mReadPerms; private ArraySet<UriPermission> mWritePerms; class ExternalToken extends Binder { UriPermissionOwner getOwner () { return UriPermissionOwner.this ; } } UriPermissionOwner(ActivityManagerService service, Object owner) { this .service = service; this .owner = owner; }
2.6.1.2 getExternalTokenLocked 返回 UriPermissionOwner 的 Binder 对象 token:
1 2 3 4 5 6 Binder getExternalTokenLocked () { if (externalToken == null ) { externalToken = new ExternalToken(); } return externalToken; }
不多说了!
2.6.1.3 fromExternalToken UriPermissionOwner 有一个方法,通过 token 找到对应的 UriPermissionOwner 实例:1 2 3 4 5 6 static UriPermissionOwner fromExternalToken (IBinder token) { if (token instanceof ExternalToken) { return ((ExternalToken)token).getOwner(); } return null ; }
不多说了!
2.6.2 调用时机 我们来看下该方法的具体调用,用 VoiceInteraction 举个例子!
2.6.2.1 new VoiceInteractionSessionConnection 首先,在创建 VoiceInteractionSessionConnection 时,我们为这个 ComponentName component 对应的组件创建了一个 UriPermissionOwner,并返回了其 Binder token!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public VoiceInteractionSessionConnection (Object lock, ComponentName component, int user, Context context, Callback callback, int callingUid, Handler handler) { mLock = lock; mSessionComponentName = component; mUser = user; mContext = context; mCallback = callback; mCallingUid = callingUid; mHandler = handler; mAm = ActivityManagerNative.getDefault(); ... ... ... IBinder permOwner = null ; try { permOwner = mAm.newUriPermissionOwner("voicesession:" + component.flattenToShortString()); } catch (RemoteException e) { Slog.w("voicesession" , "AM dead" , e); } mPermissionOwner = permOwner; ... ... ... }
2.6.2.2 deliverSessionDataLocked - VoiceInteractionSessionConnection 在 VoiceInteractionSessionConnection 的 deliverSessionDataLocked 分发语音事务是,会授予 uri permission!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private void deliverSessionDataLocked (AssistDataForActivity assistDataForActivity) { Bundle assistData = assistDataForActivity.data.getBundle( VoiceInteractionSession.KEY_DATA); AssistStructure structure = assistDataForActivity.data.getParcelable( VoiceInteractionSession.KEY_STRUCTURE); AssistContent content = assistDataForActivity.data.getParcelable( VoiceInteractionSession.KEY_CONTENT); int uid = assistDataForActivity.data.getInt(Intent.EXTRA_ASSIST_UID, -1 ); if (uid >= 0 && content != null ) { Intent intent = content.getIntent(); if (intent != null ) { ClipData data = intent.getClipData(); if (data != null && Intent.isAccessUriMode(intent.getFlags())) { grantClipDataPermissions(data, intent.getFlags(), uid, mCallingUid, mSessionComponentName.getPackageName()); } } ClipData data = content.getClipData(); if (data != null ) { grantClipDataPermissions(data, Intent.FLAG_GRANT_READ_URI_PERMISSION, uid, mCallingUid, mSessionComponentName.getPackageName()); } } try { mSession.handleAssist(assistData, structure, content, assistDataForActivity.activityIndex, assistDataForActivity.activityCount); } catch (RemoteException e) { } }
这里我们省略掉中间过程,大家可以请自去看源码:
1 grantClipDataPermissions(...) -> grantClipDataItemPermission(...) -> grantUriPermission(...)
2.6.2.3 grantUriPermission - VoiceInteractionSessionConnection grant 指定的 uid uri permission:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void grantUriPermission (Uri uri, int mode, int srcUid, int destUid, String destPkg) { if (!"content" .equals(uri.getScheme())) { return ; } long ident = Binder.clearCallingIdentity(); try { mAm.checkGrantUriPermission(srcUid, null , ContentProvider.getUriWithoutUserId(uri), mode, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(srcUid))); int sourceUserId = ContentProvider.getUserIdFromUri(uri, mUser); uri = ContentProvider.getUriWithoutUserId(uri); mAm.grantUriPermissionFromOwner(mPermissionOwner, srcUid, destPkg, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, mUser); } catch (RemoteException e) { } catch (SecurityException e) { Slog.w(TAG, "Can't propagate permission" , e); } finally { Binder.restoreCallingIdentity(ident); } }
这里传入的 mPermissionOwner 是我们前面创建的 Binder token!
2.6.3 跨进程通信 ActivityManagerProxy 中提供了相关的接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public void grantUriPermissionFromOwner (IBinder owner, int fromUid, String targetPkg, Uri uri, int mode, int sourceUserId, int targetUserId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(owner); data.writeInt(fromUid); data.writeString(targetPkg); uri.writeToParcel(data, 0 ); data.writeInt(mode); data.writeInt(sourceUserId); data.writeInt(targetUserId); mRemote.transact(GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION, data, reply, 0 ); reply.readException(); data.recycle(); reply.recycle(); }
7.1.1 的源码有一个问题:
1 GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION 被写成了 GRANT_URI_PERMISSION_TRANSACTION
我个人觉得是一个错误!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 case GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder owner = data.readStrongBinder(); int fromUid = data.readInt(); String targetPkg = data.readString(); Uri uri = Uri.CREATOR.createFromParcel(data); int mode = data.readInt(); int sourceUserId = data.readInt(); int targetUserId = data.readInt(); grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode, sourceUserId, targetUserId); reply.writeNoException(); return true ; }
3 grantPermission - PackageManagerService 权限的授予核心接口是在 PackageManagerService 中,包括运行时和安装时权限:
3.1 grantPermissionsLPw - 权限更新时调用重新授予 在更新过权限后,会再次授予应用权限,因为可能有些权限已经失效并且被移除!
这里的 replace 为 true,由于我们是更新所有的 pacakge,所以 packageOfInterest 均为 null,参数 pkg 是需要更新权限授予信息的应用!
该方法主要是在 updatePermissionsLPw 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 private void grantPermissionsLPw (PackageParser.Package pkg, boolean replace, String packageOfInterest) { final PackageSetting ps = (PackageSetting) pkg.mExtras; if (ps == null ) { return ; } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions" ); PermissionsState permissionsState = ps.getPermissionsState(); PermissionsState origPermissions = permissionsState; final int [] currentUserIds = UserManagerService.getInstance().getUserIds(); boolean runtimePermissionsRevoked = false ; int [] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY; boolean changedInstallPermission = false ; if (replace) { ps.installPermissionsFixed = false ; if (!ps.isSharedUser()) { origPermissions = new PermissionsState(permissionsState); permissionsState.reset(); } else { changedRuntimePermissionUserIds = revokeUnusedSharedUserPermissionsLPw( ps.sharedUser, UserManagerService.getInstance().getUserIds()); if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) { runtimePermissionsRevoked = true ; } } } permissionsState.setGlobalGids(mGlobalGids); final int N = pkg.requestedPermissions.size(); for (int i=0 ; i < N; i++) { final String name = pkg.requestedPermissions.get(i); final BasePermission bp = mSettings.mPermissions.get(name); if (DEBUG_INSTALL) { Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp); } if (bp == null || bp.packageSetting == null ) { if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) { Slog.w(TAG, "Unknown permission " + name + " in package " + pkg.packageName); } continue ; } final String perm = bp.name; boolean allowedSig = false ; int grant = GRANT_DENIED; if ((bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0 ) { ArraySet<String> pkgs = mAppOpPermissionPackages.get(bp.name); if (pkgs == null ) { pkgs = new ArraySet<>(); mAppOpPermissionPackages.put(bp.name, pkgs); } pkgs.add(pkg.packageName); } final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M; switch (level) { case PermissionInfo.PROTECTION_NORMAL: { grant = GRANT_INSTALL; } break ; case PermissionInfo.PROTECTION_DANGEROUS: { if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) { grant = GRANT_INSTALL; } else if (origPermissions.hasInstallPermission(bp.name)) { grant = GRANT_UPGRADE; } else if (mPromoteSystemApps && isSystemApp(ps) && mExistingSystemPackages.contains(ps.name)) { grant = GRANT_UPGRADE; } else { grant = GRANT_RUNTIME; } } break ; case PermissionInfo.PROTECTION_SIGNATURE: { allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions); if (allowedSig) { grant = GRANT_INSTALL; } } break ; } if (DEBUG_INSTALL) { Log.i(TAG, "Package " + pkg.packageName + " granting " + perm); } if (grant != GRANT_DENIED) { if (!isSystemApp(ps) && ps.installPermissionsFixed) { if (!allowedSig && !origPermissions.hasInstallPermission(perm)) { if (!isNewPlatformPermissionForPackage(perm, pkg)) { grant = GRANT_DENIED; } } } switch (grant) { case GRANT_INSTALL: { for (int userId : UserManagerService.getInstance().getUserIds()) { if (origPermissions.getRuntimePermissionState( bp.name, userId) != null ) { origPermissions.revokeRuntimePermission(bp, userId); origPermissions.updatePermissionFlags(bp, userId, PackageManager.MASK_PERMISSION_FLAGS, 0 ); changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } } if (permissionsState.grantInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) { changedInstallPermission = true ; } } break ; case GRANT_RUNTIME: { for (int userId : UserManagerService.getInstance().getUserIds()) { PermissionState permissionState = origPermissions .getRuntimePermissionState(bp.name, userId); int flags = permissionState != null ? permissionState.getFlags() : 0 ; if (origPermissions.hasRuntimePermission(bp.name, userId)) { if (permissionsState.grantRuntimePermission(bp, userId) == PermissionsState.PERMISSION_OPERATION_FAILURE) { changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } if (Build.PERMISSIONS_REVIEW_REQUIRED && appSupportsRuntimePermissions && (flags & PackageManager .FLAG_PERMISSION_REVIEW_REQUIRED) != 0 ) { flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } } else if (Build.PERMISSIONS_REVIEW_REQUIRED && !appSupportsRuntimePermissions) { if (PLATFORM_PACKAGE_NAME.equals(bp.sourcePackage)) { if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0 ) { flags |= FLAG_PERMISSION_REVIEW_REQUIRED; changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } } if (permissionsState.grantRuntimePermission(bp, userId) != PermissionsState.PERMISSION_OPERATION_FAILURE) { changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } } permissionsState.updatePermissionFlags(bp, userId, flags, flags); } } break ; case GRANT_UPGRADE: { PermissionState permissionState = origPermissions .getInstallPermissionState(bp.name); final int flags = permissionState != null ? permissionState.getFlags() : 0 ; if (origPermissions.revokeInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) { origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL, PackageManager.MASK_PERMISSION_FLAGS, 0 ); changedInstallPermission = true ; } if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0 ) { for (int userId : currentUserIds) { if (permissionsState.grantRuntimePermission(bp, userId) != PermissionsState.PERMISSION_OPERATION_FAILURE) { permissionsState.updatePermissionFlags(bp, userId, flags, flags); changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } } } } break ; default : { if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) { Slog.w(TAG, "Not granting permission " + perm + " to package " + pkg.packageName + " because it was previously installed without" ); } } break ; } } else { if (permissionsState.revokeInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) { permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL, PackageManager.MASK_PERMISSION_FLAGS, 0 ); changedInstallPermission = true ; Slog.i(TAG, "Un-granting permission " + perm + " from package " + pkg.packageName + " (protectionLevel=" + bp.protectionLevel + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags) + ")" ); } else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0 ) { if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) { Slog.w(TAG, "Not granting permission " + perm + " to package " + pkg.packageName + " (protectionLevel=" + bp.protectionLevel + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags) + ")" ); } } } } if ((changedInstallPermission || replace) && !ps.installPermissionsFixed && !isSystemApp(ps) || isUpdatedSystemApp(ps)){ ps.installPermissionsFixed = true ; } for (int userId : changedRuntimePermissionUserIds) { mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }
3.2.1 grantSignaturePermission - Signature 权限授予核心接口 grantSignaturePermission 方法用于判断签名是否能校验通过,我们在这里先忽略掉签名校验的过程,假设要么校验成功,要么校验失败!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 private boolean grantSignaturePermission (String perm, PackageParser.Package pkg, BasePermission bp, PermissionsState origPermissions) { boolean allowed; allowed = (compareSignatures( bp.packageSetting.signatures.mSignatures, pkg.mSignatures) == PackageManager.SIGNATURE_MATCH) || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures) == PackageManager.SIGNATURE_MATCH); if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0 ) { if (isSystemApp(pkg)) { if (pkg.isUpdatedSystemApp()) { final PackageSetting sysPs = mSettings .getDisabledSystemPkgLPr(pkg.packageName); if (sysPs != null && sysPs.getPermissionsState().hasInstallPermission(perm)) { if (sysPs.isPrivileged()) { allowed = true ; } } else { if (sysPs != null && sysPs.pkg != null && sysPs.isPrivileged()) { for (int j = 0 ; j < sysPs.pkg.requestedPermissions.size(); j++) { if (perm.equals(sysPs.pkg.requestedPermissions.get(j))) { allowed = true ; break ; } } } if (pkg.parentPackage != null ) { final PackageSetting disabledSysParentPs = mSettings .getDisabledSystemPkgLPr(pkg.parentPackage.packageName); if (disabledSysParentPs != null && disabledSysParentPs.pkg != null && disabledSysParentPs.isPrivileged()) { if (isPackageRequestingPermission(disabledSysParentPs.pkg, perm)) { allowed = true ; } else if (disabledSysParentPs.pkg.childPackages != null ) { final int count = disabledSysParentPs.pkg.childPackages.size(); for (int i = 0 ; i < count; i++) { PackageParser.Package disabledSysChildPkg = disabledSysParentPs.pkg.childPackages.get(i); if (isPackageRequestingPermission(disabledSysChildPkg, perm)) { allowed = true ; break ; } } } } } } } else { allowed = isPrivilegedApp(pkg); } } } if (!allowed) { if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0 && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { allowed = true ; } if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0 && pkg.packageName.equals(mRequiredInstallerPackage)) { allowed = true ; } if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0 && pkg.packageName.equals(mRequiredVerifierPackage)) { allowed = true ; } if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0 && isSystemApp(pkg)) { allowed = true ; } if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0 ) { allowed = origPermissions.hasInstallPermission(perm); } if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0 && pkg.packageName.equals(mSetupWizardPackage)) { allowed = true ; } } return allowed; }
可以看到,这里对 Signature 类型的权限做了详细的处理!
3.2 grantRuntimePermission - 运行时权限授予核心接口 授予运行时权限,其主要是在应用运行的时候,显示一个伪弹窗的 acitivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 @Override public void grantRuntimePermission (String packageName, String name, final int userId) { if (!sUserManager.exists(userId)) { Log.e(TAG, "No such user:" + userId); return ; } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, "grantRuntimePermission" ); enforceCrossUserPermission(Binder.getCallingUid(), userId, true , true , "grantRuntimePermission" ); final int uid; final SettingBase sb; synchronized (mPackages) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } final BasePermission bp = mSettings.mPermissions.get(name); if (bp == null ) { throw new IllegalArgumentException("Unknown permission: " + name); } enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp); if (Build.PERMISSIONS_REVIEW_REQUIRED && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) { return ; } uid = UserHandle.getUid(userId, pkg.applicationInfo.uid); sb = (SettingBase) pkg.mExtras; if (sb == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } final PermissionsState permissionsState = sb.getPermissionsState(); final int flags = permissionsState.getPermissionFlags(name, userId); if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 ) { throw new SecurityException("Cannot grant system fixed permission " + name + " for package " + packageName); } if (bp.isDevelopment()) { if (permissionsState.grantInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) { scheduleWriteSettingsLocked(); } return ; } if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { Slog.w(TAG, "Cannot grant runtime permission to a legacy app" ); return ; } final int result = permissionsState.grantRuntimePermission(bp, userId); switch (result) { case PermissionsState.PERMISSION_OPERATION_FAILURE: { return ; } case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: { final int appId = UserHandle.getAppId(pkg.applicationInfo.uid); mHandler.post(new Runnable() { @Override public void run () { killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED); } }); } break ; } mOnPermissionChangeListeners.onPermissionsChanged(uid); mSettings.writeRuntimePermissionsForUserLPr(userId, false ); } if (READ_EXTERNAL_STORAGE.equals(name) || WRITE_EXTERNAL_STORAGE.equals(name)) { final long token = Binder.clearCallingIdentity(); try { if (sUserManager.isInitialized(userId)) { MountServiceInternal mountServiceInternal = LocalServices.getService( MountServiceInternal.class); mountServiceInternal.onExternalStoragePolicyChanged(uid, packageName); } } finally { Binder.restoreCallingIdentity(token); } } }
3.3 grantRequestedRuntimePermissions - 安装时授予运行时权限 在签名分析 pkg install 的时候,我们有看 handlePackagePostInstall 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void handlePackagePostInstall (PackageInstalledInfo res, boolean grantPermissions, boolean killApp, String[] grantedPermissions, boolean launchedForRestore, String installerPackage, IPackageInstallObserver2 installObserver) { if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { if (res.removedInfo != null ) { res.removedInfo.sendPackageRemovedBroadcasts(killApp); } if (grantPermissions && res.pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) { grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions); }
继续来分析:
1 2 3 4 5 6 7 8 9 10 11 12 private void grantRequestedRuntimePermissions (PackageParser.Package pkg, int [] userIds, String[] grantedPermissions) { for (int userId : userIds) { grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions); } synchronized (mPackages) { mSettings.writePackageListLPr(); } }
继续跟踪:
3.3.1 grantRequestedRuntimePermissionsForUser 下面的代码很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private void grantRequestedRuntimePermissionsForUser (PackageParser.Package pkg, int userId, String[] grantedPermissions) { SettingBase sb = (SettingBase) pkg.mExtras; if (sb == null ) { return ; } PermissionsState permissionsState = sb.getPermissionsState(); final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED | PackageManager.FLAG_PERMISSION_POLICY_FIXED; for (String permission : pkg.requestedPermissions) { final BasePermission bp; synchronized (mPackages) { bp = mSettings.mPermissions.get(permission); } if (bp != null && (bp.isRuntime() || bp.isDevelopment()) && (grantedPermissions == null || ArrayUtils.contains(grantedPermissions, permission))) { final int flags = permissionsState.getPermissionFlags(permission, userId); if ((flags & immutableFlags) == 0 ) { grantRuntimePermission(pkg.packageName, permission, userId); } } } }