[toc]
基于 Android7.1.1 分析 PackageManagerService 的架构设计!
0 综述 本文来分析下 pms enable 相关的操作:
adb shell pm enable
adb shell pm disable
同样的,我们从 Pm 中看起!
1 Pm 1.1 run 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 public int run (String[] args) throws RemoteException { boolean validCommand = false ; if (args.length < 1 ) { return showUsage(); } mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE)); mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE)); mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package" )); if (mPm == null ) { System.err.println(PM_NOT_RUNNING_ERR); return 1 ; } mInstaller = mPm.getPackageInstaller(); mArgs = args; String op = args[0 ]; mNextArg = 1 ; ... ... ... if ("enable" .equals(op)) { return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); } if ("disable" .equals(op)) { return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); } if ("disable-user" .equals(op)) { return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); } if ("disable-until-used" .equals(op)) { return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED); } if ("default-state" .equals(op)) { return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); } ... ... ... }
我们可以看到,和 enable/disable 相关的 pm 指令有很多,但无疑最后调用的都是:runSetEnabledSetting,唯一的区别是参数 int state 不一样!
我们知道,在 AndroidManifest.xml 中,我们可以给 application,activity 等四大组件设置如下的属性,来设置其是否可用:
1 android:enabled="true|false"
下面,我们来看下 state 的值:
PackageManager.COMPONENT_ENABLED_STATE_ENABLED :组件或应用程序已被明确启用,无论其清单中指定了什么,适用于 setApplicationEnabledSetting 和 setComponentEnabledSetting;
PackageManager.COMPONENT_ENABLED_STATE_DISABLED :组件或应用程序已被明确禁用,无论其清单中指定了什么,适用于 setApplicationEnabledSetting 和 setComponentEnabledSetting;
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER :应用程序已被明确禁用,无论其清单中指定了什么。因为这是由于用户的请求,所以如果需要,他们可以通过适当的系统 UI 重新启用它,只适用于 setApplicationEnabledSetting;
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED :
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :组件或应用程序处于默认的 enable 状态,也就是我们在 AndroidManifest.xml 中设置的值!
接下来,我们继续分析下流程:
1.2 runSetEnabledSetting 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 private int runSetEnabledSetting (int state) { int userId = UserHandle.USER_SYSTEM; String option = nextOption(); if (option != null && option.equals("--user" )) { String optionData = nextOptionData(); if (optionData == null || !isNumber(optionData)) { System.err.println("Error: no USER_ID specified" ); return showUsage(); } else { userId = Integer.parseInt(optionData); } } String pkg = nextArg(); if (pkg == null ) { System.err.println("Error: no package or component specified" ); return showUsage(); } ComponentName cn = ComponentName.unflattenFromString(pkg); if (cn == null ) { try { mPm.setApplicationEnabledSetting(pkg, state, 0 , userId, "shell:" + android.os.Process.myUid()); System.out.println("Package " + pkg + " new state: " + enabledSettingToString( mPm.getApplicationEnabledSetting(pkg, userId))); return 0 ; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); return 1 ; } } else { try { mPm.setComponentEnabledSetting(cn, state, 0 , userId); System.out.println("Component " + cn.toShortString() + " new state: " + enabledSettingToString( mPm.getComponentEnabledSetting(cn, userId))); return 0 ; } catch (RemoteException e) { System.err.println(e.toString()); System.err.println(PM_NOT_RUNNING_ERR); return 1 ; } } }
下面会进入 PackageManagerService 中去!
2 PackageManagerService 2.1 setApplicationEnabledSetting 1 2 3 4 5 6 7 8 9 10 @Override public void setApplicationEnabledSetting (String appPackageName, int newState, int flags, int userId, String callingPackage) { if (!sUserManager.exists(userId)) return ; if (callingPackage == null ) { callingPackage = Integer.toString(Binder.getCallingUid()); } setEnabledSetting(appPackageName, null , newState, flags, userId, callingPackage); }
2.2 setComponentEnabledSetting 1 2 3 4 5 6 7 8 @Override public void setComponentEnabledSetting (ComponentName componentName, int newState, int flags, int userId) { if (!sUserManager.exists(userId)) return ; setEnabledSetting(componentName.getPackageName(), componentName.getClassName(), newState, flags, userId, null ); }
2.3 setEnabledSetting - 核心入口 可以看到,无论 application 环视 component,最后调用的都是该方法:
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 private void setEnabledSetting (final String packageName, String className, int newState, final int flags, int userId, String callingPackage) { if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT || newState == COMPONENT_ENABLED_STATE_ENABLED || newState == COMPONENT_ENABLED_STATE_DISABLED || newState == COMPONENT_ENABLED_STATE_DISABLED_USER || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) { throw new IllegalArgumentException("Invalid new component state: " + newState); } PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); final int permission; if (uid == Process.SYSTEM_UID) { permission = PackageManager.PERMISSION_GRANTED; } else { permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); } enforceCrossUserPermission(uid, userId, false , true , "set enabled" ); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); boolean sendNow = false ; boolean isApp = (className == null ); String componentName = isApp ? packageName : className; int packageUid = -1 ; ArrayList<String> components; synchronized (mPackages) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null ) { if (className == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } throw new IllegalArgumentException( "Unknown component: " + packageName + "/" + className); } } if (!UserHandle.isSameApp(uid, pkgSetting.appId)) { if (!allowedByPermission) { throw new SecurityException( "Permission Denial: attempt to change component state from pid=" + Binder.getCallingPid() + ", uid=" + uid + ", package uid=" + pkgSetting.appId); } if (mProtectedPackages.isPackageStateProtected(userId, packageName)) { throw new SecurityException("Cannot disable a protected package: " + packageName); } } synchronized (mPackages) { if (uid == Process.SHELL_UID) { int oldState = pkgSetting.getEnabled(userId); if (className == null && (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER || oldState == COMPONENT_ENABLED_STATE_DEFAULT || oldState == COMPONENT_ENABLED_STATE_ENABLED) && (newState == COMPONENT_ENABLED_STATE_DISABLED_USER || newState == COMPONENT_ENABLED_STATE_DEFAULT || newState == COMPONENT_ENABLED_STATE_ENABLED)) { } else { throw new SecurityException( "Shell cannot change component state for " + packageName + "/" + className + " to " + newState); } } if (className == null ) { if (pkgSetting.getEnabled(userId) == newState) { return ; } if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { callingPackage = null ; } pkgSetting.setEnabled(newState, userId, callingPackage); } else { PackageParser.Package pkg = pkgSetting.pkg; if (pkg == null || !pkg.hasComponentClassName(className)) { if (pkg != null && pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) { throw new IllegalArgumentException("Component class " + className + " does not exist in " + packageName); } else { Slog.w(TAG, "Failed setComponentEnabledSetting: component class " + className + " does not exist in " + packageName); } } switch (newState) { case COMPONENT_ENABLED_STATE_ENABLED: if (!pkgSetting.enableComponentLPw(className, userId)) { return ; } break ; case COMPONENT_ENABLED_STATE_DISABLED: if (!pkgSetting.disableComponentLPw(className, userId)) { return ; } break ; case COMPONENT_ENABLED_STATE_DEFAULT: if (!pkgSetting.restoreComponentLPw(className, userId)) { return ; } break ; default : Slog.e(TAG, "Invalid new component state: " + newState); return ; } } scheduleWritePackageRestrictionsLocked(userId); components = mPendingBroadcasts.get(userId, packageName); final boolean newPackage = components == null ; if (newPackage) { components = new ArrayList<String>(); } if (!components.contains(componentName)) { components.add(componentName); } if ((flags&PackageManager.DONT_KILL_APP) == 0 ) { sendNow = true ; mPendingBroadcasts.remove(userId, packageName); } else { if (newPackage) { mPendingBroadcasts.put(userId, packageName, components); } if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); } } } long callingId = Binder.clearCallingIdentity(); try { if (sendNow) { packageUid = UserHandle.getUid(userId, pkgSetting.appId); sendPackageChangedBroadcast(packageName, (flags&PackageManager.DONT_KILL_APP) != 0 , components, packageUid); } } finally { Binder.restoreCallingIdentity(callingId); } }
Pms 内部有一个 PendingPackageBroadcasts 对象 mPendingBroadcasts,用于保存需要延迟返送的广播:
1 final PendingPackageBroadcasts mPendingBroadcasts = new PendingPackageBroadcasts();
我们来看下 PendingPackageBroadcasts 的定义:
1 2 3 4 5 6 7 8 9 10 static class PendingPackageBroadcasts { final SparseArray<ArrayMap<String, ArrayList<String>>> mUidMap; public PendingPackageBroadcasts () { mUidMap = new SparseArray<ArrayMap<String, ArrayList<String>>>(2 ); } ... ... ... }
可以看到,其内部有一个 mUidMap 的 SparseArray 数组,保存的数据结构满足如下关系:
1 userId --> ArrayMap< packageName --> ArrayList<componentName> >
2.3.1 sendPackageChangedBroadcast 发送 ACTION_PACKAGE_CHANGED 的广播:
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 private void sendPackageChangedBroadcast (String packageName, boolean killFlag, ArrayList<String> componentNames, int packageUid) { if (DEBUG_INSTALL) Log.v(TAG, "Sending package changed: package=" + packageName + " components=" + componentNames); Bundle extras = new Bundle(4 ); extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0 )); String nameList[] = new String[componentNames.size()]; componentNames.toArray(nameList); extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList); extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag); extras.putInt(Intent.EXTRA_UID, packageUid); final int flags = !componentNames.contains(packageName) ? Intent.FLAG_RECEIVER_REGISTERED_ONLY : 0 ; sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null , null , new int [] {UserHandle.getUserId(packageUid)}); }
不多说了!
3 PackageSetting 下面的方法确切的讲是 PackageSetting 的父类 PackageSettingBase 父类的方法:
3.1 getEnabled 获得指定 user 下的 app 的 enabled 状态:
1 2 3 4 int getEnabled (int userId) { return readUserState(userId).enabled; }
3.1.1 readUserState PackageSetting 内部有一个 SparseArray 数组:userState
1 2 3 4 5 6 7 public PackageUserState readUserState (int userId) { PackageUserState state = userState.get(userId); if (state != null ) { return state; } return DEFAULT_USER_STATE; }
3.2 setEnabled 设置指定 user 下的 app 的 enabled 状态:
1 2 3 4 5 6 7 void setEnabled (int state, int userId, String callingPackage) { PackageUserState st = modifyUserState(userId); st.enabled = state; st.lastDisableAppCaller = callingPackage; }
3.2.1 modifyUserState 1 2 3 4 5 6 7 8 private PackageUserState modifyUserState (int userId) { PackageUserState state = userState.get(userId); if (state == null ) { state = new PackageUserState(); userState.put(userId, state); } return state; }
3.3 enableComponentLPw enable 指定组件:
1 2 3 4 5 6 7 8 9 10 boolean enableComponentLPw (String componentClassName, int userId) { PackageUserState state = modifyUserStateComponents(userId, false , true ); boolean changed = state.disabledComponents != null ? state.disabledComponents.remove(componentClassName) : false ; changed |= state.enabledComponents.add(componentClassName); return changed; }
3.3.1 modifyUserStateComponents modify 方法是对 PackageUserState 做一个初始化,然后返回:
1 2 3 4 5 6 7 8 9 10 11 12 13 PackageUserState modifyUserStateComponents (int userId, boolean disabled, boolean enabled) { PackageUserState state = modifyUserState(userId); if (disabled && state.disabledComponents == null ) { state.disabledComponents = new ArraySet<String>(1 ); } if (enabled && state.enabledComponents == null ) { state.enabledComponents = new ArraySet<String>(1 ); } return state; }
PackageUserState 内部有两个 ArraySet 集合:
1 2 public ArraySet<String> disabledComponents; public ArraySet<String> enabledComponents;
… …
3.3 disableComponentLPw disable 指定组件:
1 2 3 4 5 6 7 8 9 10 boolean disableComponentLPw (String componentClassName, int userId) { PackageUserState state = modifyUserStateComponents(userId, true , false ); boolean changed = state.enabledComponents != null ? state.enabledComponents.remove(componentClassName) : false ; changed |= state.disabledComponents.add(componentClassName); return changed; }
3.4 restoreComponentLPw restore 指定组件:
1 2 3 4 5 6 7 8 9 10 11 boolean restoreComponentLPw (String componentClassName, int userId) { PackageUserState state = modifyUserStateComponents(userId, true , true ); boolean changed = state.disabledComponents != null ? state.disabledComponents.remove(componentClassName) : false ; changed |= state.enabledComponents != null ? state.enabledComponents.remove(componentClassName) : false ; return changed; }
不多说了!
4 PackageHandler 然后我们来看下 PackageHandler 对于消息的处理:
4.1 doHandleMessage[SEND_PENDING_BROADCAST] 然后我们来看下延迟发送广播的处理:
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 case SEND_PENDING_BROADCAST: { String packages[]; ArrayList<String> components[]; int size = 0 ; int uids[]; Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); synchronized (mPackages) { if (mPendingBroadcasts == null ) { return ; } size = mPendingBroadcasts.size(); if (size <= 0 ) { return ; } packages = new String[size]; components = new ArrayList[size]; uids = new int [size]; int i = 0 ; for (int n = 0 ; n < mPendingBroadcasts.userIdCount(); n++) { int packageUserId = mPendingBroadcasts.userIdAt(n); Iterator<Map.Entry<String, ArrayList<String>>> it = mPendingBroadcasts.packagesForUserId(packageUserId) .entrySet().iterator(); while (it.hasNext() && i < size) { Map.Entry<String, ArrayList<String>> ent = it.next(); packages[i] = ent.getKey(); components[i] = ent.getValue(); PackageSetting ps = mSettings.mPackages.get(ent.getKey()); uids[i] = (ps != null ) ? UserHandle.getUid(packageUserId, ps.appId) : -1 ; i++; } } size = i; mPendingBroadcasts.clear(); } for (int i = 0 ; i < size; i++) { sendPackageChangedBroadcast(packages[i], true , components[i], uids[i]); } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); break ; }
5 不同的 enable 状态的区别