[toc]
基于 Android 7.1.1 源码分析 PackageManagerService 的架构和逻辑实现!
0 综述 本篇文章总结下 uninstall package 的过程,一般来说,卸载一个应用有如下的方式:
adb uninstall(最终调用的还是 pm uninstall/cmd package uninstall);
adb cmd package uninstall;
adb shell pm uninstall;
进入应用管理器中,手动触发卸载(进入 packageInstaller);
这里我们先来看通过 adb 指令 uninstall 的过程:
1 adb uninstall - commandline::adb_commandline 同样的 adb uninstall 的执行也是从 system/core/adb/commandline.cpp 开始:
adb_commandline 中会设置到大量的 adb 指令的处理,这里我们只关注 adb install 的处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int adb_commandline (int argc, const char **argv) { ... ... ... else if (!strcmp(argv[0 ], "uninstall" )) { if (argc < 2 ) return usage(); if (_use_legacy_install()) { return uninstall_app_legacy(transport_type, serial, argc, argv); } return uninstall_app(transport_type, serial, argc, argv); } ... ... ... usage(); return 1 ; }
这里看到,如果支持 cmd 命令的情况下,_use_legacy_install() 方法返回 false,会调用 uninstall_app;不支持的话,执行 uninstall_app_legacy 方法!
Android cmd 命令功能非常强大,包含了我们之前使用 am pm 等等的命令,这里我们不深入分析 cmd 的命令的实现,我们关注和 uninstall 相关的逻辑!
下面继续分析,进一步的安装过程:
1.1 cmd uninstall - 支持 cmd 指令 1.1.1 commandline::uninstall_app 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static int uninstall_app (TransportType transport, const char * serial, int argc, const char ** argv) { std::string cmd = "cmd package" ; while (argc-- > 0 ) { if (strcmp(*argv, "-k" ) == 0 ) { printf( "The -k option uninstalls the application while retaining the data/cache.\n" "At the moment, there is no way to remove the remaining data.\n" "You will have to reinstall the application with the same signature, and fully uninstall it.\n" "If you truly wish to continue, execute 'adb shell cmd package uninstall -k'.\n" ); return EXIT_FAILURE; } cmd += " " + escape_arg(*argv++); } return send_shell_command(transport, serial, cmd, false ); }
1.2 pm uninstall - 不支持 cmd 指令 1.2.1 commandline::uninstall_app_legacy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static int uninstall_app_legacy (TransportType transport, const char * serial, int argc, const char ** argv) { int i; for (i = 1 ; i < argc; i++) { if (!strcmp(argv[i], "-k" )) { printf( "The -k option uninstalls the application while retaining the data/cache.\n" "At the moment, there is no way to remove the remaining data.\n" "You will have to reinstall the application with the same signature, and fully uninstall it.\n" "If you truly wish to continue, execute 'adb shell pm uninstall -k'\n." ); return EXIT_FAILURE; } } return pm_command(transport, serial, argc, argv); }
1.2.2 commandline::pm_command 1 2 3 4 5 6 7 8 9 10 static int pm_command (TransportType transport, const char * serial, int argc, const char ** argv) { std::string cmd = "pm" ; while (argc-- > 0 ) { cmd += " " + escape_arg(*argv++); } return send_shell_command(transport, serial, cmd, false ); }
1.2.3 commandline::send_shell_command 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 int send_shell_command (TransportType transport_type, const char * serial, const std::string& command, bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) { int fd; bool use_shell_protocol = false ; while (true ) { bool attempt_connection = true ; if (!disable_shell_protocol) { FeatureSet features; std::string error; if (adb_get_feature_set(&features, &error)) { use_shell_protocol = CanUseFeature(features, kFeatureShell2); } else { attempt_connection = false ; } } if (attempt_connection) { std::string error; std::string service_string = ShellServiceString(use_shell_protocol, "" , command); fd = adb_connect(service_string, &error); if (fd >= 0 ) { break ; } } fprintf(stderr, "- waiting for device -\n" ); if (!wait_for_device("wait-for-device" , transport_type, serial)) { return 1 ; } } int exit_code = read_and_dump(fd, use_shell_protocol, callback); if (adb_close(fd) < 0 ) { PLOG(ERROR) << "failure closing FD " << fd; } return exit_code; }
可以看到,最后都是调用 shell 执行相关指令!
前面我们有分析过:
cmd package uninstall 最后调用的是 PackageManagerShellCommand 相关方法;
pm uninstall 最后调用的是 pm 相关方法;
2 Pm install 对于 pm 命令的执行过程,我们不在过多分析,直接进入重点:
2.1 runUninstall 1 2 3 4 private int runUninstall () { return runShellCommand("package" , mArgs); }
2.2 runShellCommand 我们看到,我们传入的 Service name 是 “package”,其实看到这里,我们已经能猜到了,其和 cmd install 一样,最后会调用了 PackageManagerShellCommand 的 onCommand 方法!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private int runShellCommand (String serviceName, String[] args) { final HandlerThread handlerThread = new HandlerThread("results" ); handlerThread.start(); try { ServiceManager.getService(serviceName).shellCommand( FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, args, new ResultReceiver(new Handler(handlerThread.getLooper()))); return 0 ; } catch (RemoteException e) { e.printStackTrace(); } finally { handlerThread.quitSafely(); } return -1 ; }
我们可以去 pms 的代码中看到,pms 有如下的逻辑:
1 2 3 4 5 6 7 @Override public void onShellCommand (FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) { (new PackageManagerShellCommand(this )).exec( this , in, out, err, args, resultReceiver); }
PackageManagerShellCommand 继承了 ShellCommand, exec 内部会触发 onCommand 方法,有兴趣大家可以去学习,这里不关注!!
3 PackageManagerShellCommand 3.1 runUninstall 我们来分析下 runUninstall 的逻辑: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 private int runUninstall () throws RemoteException { final PrintWriter pw = getOutPrintWriter(); int flags = 0 ; int userId = UserHandle.USER_ALL; String opt; while ((opt = getNextOption()) != null ) { switch (opt) { case "-k" : flags |= PackageManager.DELETE_KEEP_DATA; break ; case "--user" : userId = UserHandle.parseUserArg(getNextArgRequired()); break ; default : pw.println("Error: Unknown option: " + opt); return 1 ; } } final String packageName = getNextArg(); if (packageName == null ) { pw.println("Error: package name not specified" ); return 1 ; } final String splitName = getNextArg(); if (splitName != null ) { return runRemoveSplit(packageName, splitName); } userId = translateUserId(userId, "runUninstall" ); if (userId == UserHandle.USER_ALL) { userId = UserHandle.USER_SYSTEM; flags |= PackageManager.DELETE_ALL_USERS; } else { final PackageInfo info = mInterface.getPackageInfo(packageName, 0 , userId); if (info == null ) { pw.println("Failure [not installed for " + userId + "]" ); return 1 ; } final boolean isSystem = (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ; if (isSystem) { flags |= PackageManager.DELETE_SYSTEM_APP; } } final LocalIntentReceiver receiver = new LocalIntentReceiver(); mInterface.getPackageInstaller().uninstall(packageName, null , flags, receiver.getIntentSender(), userId); final Intent result = receiver.getResult(); final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); if (status == PackageInstaller.STATUS_SUCCESS) { pw.println("Success" ); return 0 ; } else { pw.println("Failure [" + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]" ); return 1 ; } }
这里的 mInterface.getPackageInstaller() 返回的是 PackageInstallerService,下面我们去 PackageInstallerService 中看看:
3.1.1 translateUserId 如果 uninstall 指定的 user,那么这里会对 userId 做一个转换处理:1 2 3 4 private int translateUserId (int userId, String logContext) { return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true , true , logContext, "pm command" ); }
3.1.2 LocalIntentReceiver LocalIntentReceiver 主要用于接收最终的返回结果,以及和其他模块通信:
3.1.2.1 new LocalIntentReceiver 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private static class LocalIntentReceiver { private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>(); private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { @Override public void send (int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { try { mResult.offer(intent, 5 , TimeUnit.SECONDS); } catch (InterruptedException e) { throw new RuntimeException(e); } } };
不多数说了!!
3.1.2.2 getIntentSender 返回代理对象,用于跨进程通信:1 2 3 public IntentSender getIntentSender () { return new IntentSender((IIntentSender) mLocalSender); }
3.1.2.2 getResult 从内部的阻塞队列中返回结果!
1 2 3 4 5 6 7 public Intent getResult () { try { return mResult.take(); } catch (InterruptedException e) { throw new RuntimeException(e); } }
3.2 runRemoveSplit 我们来看下删除 split apk 的逻辑!
参数 String packageName 是主 pkg,String splitName 则是 split apk 的包名!
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 private int runRemoveSplit (String packageName, String splitName) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; sessionParams.appPackageName = packageName; final int sessionId = doCreateSession(sessionParams, null , UserHandle.USER_ALL); boolean abandonSession = true ; try { if (doRemoveSplit(sessionId, splitName, false ) != PackageInstaller.STATUS_SUCCESS) { return 1 ; } if (doCommitSession(sessionId, false ) != PackageInstaller.STATUS_SUCCESS) { return 1 ; } abandonSession = false ; pw.println("Success" ); return 0 ; } finally { if (abandonSession) { try { doAbandonSession(sessionId, false ); } catch (Exception ignore) { } } } }
这里先创建了一个 SessionParams,参数均是 @hide 的,这里我省略了!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static class SessionParams implements Parcelable { public int mode = MODE_INVALID; public int installFlags; public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; public long sizeBytes = -1 ; public String appPackageName; public Bitmap appIcon; public String appLabel; public long appIconLastModified = -1 ; public Uri originatingUri; public int originatingUid = UID_UNKNOWN; public Uri referrerUri; public String abiOverride; public String volumeUuid; public String[] grantedRuntimePermissions; public SessionParams (int mode) { this .mode = mode; } ... ... ... }
可以看到,对于 remove split apk,其流程和 install 很类似!
3.2.1 doCreateSession 创建事务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private int doCreateSession (SessionParams params, String installerPackageName, int userId) throws RemoteException { userId = translateUserId(userId, "runInstallCreate" ); if (userId == UserHandle.USER_ALL) { userId = UserHandle.USER_SYSTEM; params.installFlags |= PackageManager.INSTALL_ALL_USERS; } final int sessionId = mInterface.getPackageInstaller() .createSession(params, installerPackageName, userId); return sessionId; }
这里和 install 很类似!
3.2.2 doRemoveSplit 移除 split apk,这里是真正的对 split apk 做处理,前面只是创建了一个主 apk 的 install 食物:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private int doRemoveSplit (int sessionId, String splitName, boolean logSuccess) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); PackageInstaller.Session session = null ; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); session.removeSplit(splitName); if (logSuccess) { pw.println("Success" ); } return 0 ; } catch (IOException e) { pw.println("Error: failed to remove split; " + e.getMessage()); return 1 ; } finally { IoUtils.closeQuietly(session); } }
Session 其实很简单:1 2 3 4 public static class Session implements Closeable { private IPackageInstallerSession mSession; ... ... ... }
不多数了!
继续分析,我们看看 removeSplit 发生了什么:
3.2.3 doCommitSession 提交事务:
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 int doCommitSession (int sessionId, boolean logSuccess) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); PackageInstaller.Session session = null ; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); final LocalIntentReceiver receiver = new LocalIntentReceiver(); session.commit(receiver.getIntentSender()); final Intent result = receiver.getResult(); final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); if (status == PackageInstaller.STATUS_SUCCESS) { if (logSuccess) { pw.println("Success" ); } } else { pw.println("Failure [" + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]" ); } return status; } finally { IoUtils.closeQuietly(session); } }
4 PackageInstallerService 4.1 uninstall 这里我们说一下参数 IntentSender statusReceiver,其是前面 LocalIntentReceiver.getIntentSender() 返回的 IntentSender 实例:
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 @Override public void uninstall (String packageName, String callerPackageName, int flags, IntentSender statusReceiver, int userId) { final int callingUid = Binder.getCallingUid(); mPm.enforceCrossUserPermission(callingUid, userId, true , true , "uninstall" ); if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) { mAppOps.checkPackage(callingUid, callerPackageName); } DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService( Context.DEVICE_POLICY_SERVICE); boolean isDeviceOwner = (dpm != null ) && dpm.isDeviceOwnerAppOnCallingUser( callerPackageName); final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, statusReceiver, packageName, isDeviceOwner, userId); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) == PackageManager.PERMISSION_GRANTED) { mPm.deletePackage(packageName, adapter.getBinder(), userId, flags); } else if (isDeviceOwner) { long ident = Binder.clearCallingIdentity(); try { mPm.deletePackage(packageName, adapter.getBinder(), userId, flags); } finally { Binder.restoreCallingIdentity(ident); } } else { final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); intent.setData(Uri.fromParts("package" , packageName, null )); intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder()); adapter.onUserActionRequired(intent); } }
代码很简单,不多说了!
4.1.1 PackageDeleteObserverAdapter 4.1.1.1 new PackageInstallerService 创建了一个 package delete 监听器!
boolean showNotification 表示是否需要显示通知,上面传入的是 isDeviceOwner,就是说如果是设备拥有者,那么一定会显示通知!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static class PackageDeleteObserverAdapter extends PackageDeleteObserver { private final Context mContext; private final IntentSender mTarget; private final String mPackageName; private final Notification mNotification; public PackageDeleteObserverAdapter (Context context, IntentSender target, String packageName, boolean showNotification, int userId) { mContext = context; mTarget = target; mPackageName = packageName; if (showNotification) { mNotification = buildSuccessNotification(mContext, mContext.getResources().getString(R.string.package_deleted_device_owner), packageName, userId); } else { mNotification = null ; } } ... ... ... }
不多说了!
4.1.1.2 onUserActionRequired 当没有权限直接卸载时,需要用户参与卸载时,会触发该方法,可以看到,该方法最后会发送 Intent.ACTION_UNINSTALL_PACKAGE 到 PackageInstaller 中去!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override public void onUserActionRequired (Intent intent) { final Intent fillIn = new Intent(); fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { mTarget.sendIntent(mContext, 0 , fillIn, null , null ); } catch (SendIntentException ignored) { } }
对于传入的参数 intent:
1 2 3 4 5 6 final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);intent.setData(Uri.fromParts("package" , packageName, null )); intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder());
接着,在 onUserActionRequired 有对参数 intent 进行了进一步的安装!
关于 PackageInstaller.STATUS_PENDING_USER_ACTION 的广播,我们后面再分析,这里先不关注!
4.1.1.3 onPackageDeleted 卸载成功后回调该接口:
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 @Override public void onPackageDeleted (String basePackageName, int returnCode, String msg) { if (PackageManager.DELETE_SUCCEEDED == returnCode && mNotification != null ) { NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(basePackageName, 0 , mNotification); } final Intent fillIn = new Intent(); fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageManager.deleteStatusToPublicStatus(returnCode)); fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, PackageManager.deleteStatusToString(returnCode, msg)); fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); try { mTarget.sendIntent(mContext, 0 , fillIn, null , null ); } catch (SendIntentException ignored) { } }
不多说了!!
5 PackageManagerService 卸载的核心接口在 PackageManagerService 中:
5.1 deletePackage 开始卸载删除应用:
我们知道,在前面的时候,如果是从所有用户下卸载,那么 userId 和 flags 会有如下的变化:
userId = UserHandle.USER_SYSTEM; flags |= PackageManager.DELETE_ALL_USERS;
如果是从指定用户下卸载,那么 userId 就是我们指定的用户!
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 @Override public void deletePackage (final String packageName, final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DELETE_PACKAGES, null ); Preconditions.checkNotNull(packageName); Preconditions.checkNotNull(observer); final int uid = Binder.getCallingUid(); if (!isOrphaned(packageName) && !isCallerAllowedToSilentlyUninstall(uid, packageName)) { try { final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null )); intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder()); observer.onUserActionRequired(intent); } catch (RemoteException re) { } return ; } final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0 ; final int [] users = deleteAllUsers ? sUserManager.getUserIds() : new int []{ userId }; if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1 )) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "deletePackage for user " + userId); } if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) { try { observer.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_USER_RESTRICTED, null ); } catch (RemoteException re) { } return ; } if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) { try { observer.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_OWNER_BLOCKED, null ); } catch (RemoteException re) { } return ; } if (DEBUG_REMOVE) { Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId + " deleteAllUsers: " + deleteAllUsers ); } mHandler.post(new Runnable() { public void run () { mHandler.removeCallbacks(this ); int returnCode; if (!deleteAllUsers) { returnCode = deletePackageX(packageName, userId, deleteFlags); } else { int [] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users); if (ArrayUtils.isEmpty(blockUninstallUserIds)) { returnCode = deletePackageX(packageName, userId, deleteFlags); } else { final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS; for (int userId : users) { if (!ArrayUtils.contains(blockUninstallUserIds, userId)) { returnCode = deletePackageX(packageName, userId, userFlags); if (returnCode != PackageManager.DELETE_SUCCEEDED) { Slog.w(TAG, "Package delete failed for user " + userId + ", returnCode " + returnCode); } } } returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED; } } try { observer.onPackageDeleted(packageName, returnCode, null ); } catch (RemoteException e) { Log.i(TAG, "Observer no longer exists." ); } } }); }
过程分析的很详细!
5.1.1 isOrphaned 判断该应用是否是孤立的:
1 2 3 4 5 6 7 public boolean isOrphaned (String packageName) { synchronized (mPackages) { return mSettings.isOrphaned(packageName); } }
5.1.1.1 Settings.isOrphaned 1 2 3 4 5 6 7 8 boolean isOrphaned (String packageName) { final PackageSetting pkg = mPackages.get(packageName); if (pkg == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } return pkg.isOrphaned; }
不多数了!!
5.1.2 isCallerAllowedToSilentlyUninstall 判断是否允许静默卸载:
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 private boolean isCallerAllowedToSilentlyUninstall (int callingUid, String pkgName) { if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID) { return true ; } final int callingUserId = UserHandle.getUserId(callingUid); if (callingUid == getPackageUid(getInstallerPackageName(pkgName), 0 , callingUserId)) { return true ; } if (mRequiredVerifierPackage != null && callingUid == getPackageUid(mRequiredVerifierPackage, 0 , callingUserId)) { return true ; } if (mRequiredUninstallerPackage != null && callingUid == getPackageUid(mRequiredUninstallerPackage, 0 , callingUserId)) { return true ; } if (mStorageManagerPackage != null && callingUid == getPackageUid(mStorageManagerPackage, 0 , callingUserId)) { return true ; } return false ; }
5.1.2.1 getPackageUid 获得 pacakge 的 uid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Override public int getPackageUid (String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return -1 ; flags = updateFlagsForPackage(flags, userId, packageName); enforceCrossUserPermission(Binder.getCallingUid(), userId, false , false , "get package uid" ); synchronized (mPackages) { final PackageParser.Package p = mPackages.get(packageName); if (p != null && p.isMatch(flags)) { return UserHandle.getUid(userId, p.applicationInfo.uid); } if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0 ) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null && ps.isMatch(flags)) { return UserHandle.getUid(userId, ps.appId); } } } return -1 ; }
5.1.2.2 getInstallerPackageName 获得 package 的安装者:
1 2 3 4 5 6 7 @Override public String getInstallerPackageName (String packageName) { synchronized (mPackages) { return mSettings.getInstallerPackageNameLPr(packageName); } }
5.1.2.2.1 Settings.getInstallerPackageNameLPr 1 2 3 4 5 6 7 8 String getInstallerPackageNameLPr (String packageName) { final PackageSetting pkg = mPackages.get(packageName); if (pkg == null ) { throw new IllegalArgumentException("Unknown package: " + packageName); } return pkg.installerPackageName; }
不多说了!
5.1.3 isUserRestricted 判断在 userId 是否有用户限制,限制由 restrictionKey 指定:
1 2 3 4 5 6 7 8 boolean isUserRestricted (int userId, String restrictionKey) { Bundle restrictions = sUserManager.getUserRestrictions(userId); if (restrictions.getBoolean(restrictionKey, false )) { Log.w(TAG, "User is restricted: " + restrictionKey); return true ; } return false ; }
5.1.4 getBlockUninstallForUser 判断该 package 是否处于 block uninstall 的状态:
1 2 3 4 5 6 7 8 9 10 11 12 @Override public boolean getBlockUninstallForUser (String packageName, int userId) { synchronized (mPackages) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null ) { Log.i(TAG, "Package doesn't exist in get block uninstall " + packageName); return false ; } return ps.getBlockUninstall(userId); } }
5.1.4.1 PackageSettingBase.getBlockUninstall PackageSetting 继承了 PackageSettingBase,getBlockUninstall 方法是在父类中:
1 2 3 4 boolean getBlockUninstall (int userId) { return readUserState(userId).blockUninstall; }
PackageUserState 实例,表示每个 pkg 在对应的 user 下的使用状态,其在我们分析 pms 的启动时有分析过,这里不多说了!
5.1.4.2 PackageSettingBase.readUserState 1 2 3 4 5 6 7 8 9 public PackageUserState readUserState (int userId) { PackageUserState state = userState.get(userId); if (state != null ) { return state; } return DEFAULT_USER_STATE; }
这里的 DEFAULT_USER_STATE 是一个 PackageUserState 对象!!
1 private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
5.1.5 getBlockUninstallForUsers 该方法用于获得该 package 在多个 user 下的 block uninstall 状态:
1 2 3 4 5 6 7 8 9 10 11 private int [] getBlockUninstallForUsers(String packageName, int [] userIds) { int [] result = EMPTY_INT_ARRAY; for (int userId : userIds) { if (getBlockUninstallForUser(packageName, userId)) { result = ArrayUtils.appendInt(result, userId); } } return result; }
不多说了!!
5.2 deletePackageX 接着是进入第二阶段的卸载:
如果可以卸载所有 user 下的安装,那么 deleteFlags 会被设置为 PackageManager.DELETE_ALL_USERS; 而 user 则是每一个用户;
如果是卸载指定的 user 下的安装,那么 deleteFlags 不会设置为 PackageManager.DELETE_ALL_USERS;
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 private int deletePackageX (String packageName, int userId, int deleteFlags) { final PackageRemovedInfo info = new PackageRemovedInfo(); final boolean res; final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0 ? UserHandle.USER_ALL : userId; if (isPackageDeviceAdmin(packageName, removeUser)) { Slog.w(TAG, "Not removing package " + packageName + ": has active device admin" ); return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER; } PackageSetting uninstalledPs = null ; int [] allUsers; synchronized (mPackages) { uninstalledPs = mSettings.mPackages.get(packageName); if (uninstalledPs == null ) { Slog.w(TAG, "Not removing non-existent package " + packageName); return PackageManager.DELETE_FAILED_INTERNAL_ERROR; } allUsers = sUserManager.getUserIds(); info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true ); } final int freezeUser; if (isUpdatedSystemApp(uninstalledPs) && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0 )) { freezeUser = UserHandle.USER_ALL; } else { freezeUser = removeUser; } synchronized (mInstallLock) { if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId); try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser, deleteFlags, "deletePackageX" )) { res = deletePackageLIF(packageName, UserHandle.of(removeUser), true , allUsers, deleteFlags | REMOVE_CHATTY, info, true , null ); } synchronized (mPackages) { if (res) { mEphemeralApplicationRegistry.onPackageUninstalledLPw(uninstalledPs.pkg); } } } if (res) { final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0 ; info.sendPackageRemovedBroadcasts(killApp); info.sendSystemPackageUpdatedBroadcasts(); info.sendSystemPackageAppearedBroadcasts(); } Runtime.getRuntime().gc(); if (info.args != null ) { synchronized (mInstallLock) { info.args.doPostDeleteLI(true ); } } return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; }
流程已经分析的很详细了!!
5.2.1 PackageRemovedInfo 5.2.1.1 new PackageRemovedInfo 创建一个 PackageRemovedInfo 实例,分装要卸载的 apk 的相关信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class PackageRemovedInfo { String removedPackage; int uid = -1 ; int removedAppId = -1 ; int [] origUsers; int [] removedUsers = null ; boolean isRemovedPackageSystemUpdate = false ; boolean isUpdate; boolean dataRemoved; boolean removedForAllUsers; InstallArgs args = null ; ArrayMap<String, PackageRemovedInfo> removedChildPackages; ArrayMap<String, PackageInstalledInfo> appearedChildPackages; ... ... ... }
同时,PackageRemovedInfo 内部也有很多的方法,用于发送广播,这里我们先分析当前流程能用的到的!!
5.2.1.2 sendPackageRemovedBroadcasts 发送升级包被移除的广播:
1 2 3 4 5 6 7 8 9 10 void sendPackageRemovedBroadcasts (boolean killApp) { sendPackageRemovedBroadcastInternal(killApp); final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageRemovedInfo childInfo = removedChildPackages.valueAt(i); childInfo.sendPackageRemovedBroadcastInternal(killApp); } }
逻辑简单,不多说了!
5.2.1.2.1 sendPackageRemovedBroadcastInternal 发送 removed 的广播:
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 private void sendPackageRemovedBroadcastInternal (boolean killApp) { Bundle extras = new Bundle(2 ); extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid); extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved); extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp); if (isUpdate || isRemovedPackageSystemUpdate) { extras.putBoolean(Intent.EXTRA_REPLACING, true ); } extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers); if (removedPackage != null ) { sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED , removedPackage, extras, 0 , null , null , removedUsers); if (dataRemoved && !isRemovedPackageSystemUpdate) { sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage, extras, 0 , null , null , removedUsers); } } if (removedAppId >= 0 ) { sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null , extras, 0 , null , null , removedUsers); } }
这里就不不多说了!
5.2.1.3 sendSystemPackageUpdatedBroadcasts 发送 system app updated 广播:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void sendSystemPackageUpdatedBroadcasts () { if (isRemovedPackageSystemUpdate) { sendSystemPackageUpdatedBroadcastsInternal(); final int childCount = (removedChildPackages != null ) ? removedChildPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageRemovedInfo childInfo = removedChildPackages.valueAt(i); if (childInfo.isRemovedPackageSystemUpdate) { childInfo.sendSystemPackageUpdatedBroadcastsInternal(); } } } }
逻辑简单,不多说了!
5.2.1.3.1 sendSystemPackageUpdatedBroadcastsInternal 核心方法:
1 2 3 4 5 6 7 8 9 10 11 12 private void sendSystemPackageUpdatedBroadcastsInternal () { Bundle extras = new Bundle(2 ); extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid); extras.putBoolean(Intent.EXTRA_REPLACING, true ); sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras, 0 , null , null , null ); sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage, extras, 0 , null , null , null ); sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null , null , 0 , removedPackage, null , null ); }
不多说了!
5.2.1.4 sendSystemPackageAppearedBroadcasts 发送 system app appeared 广播,针对于 child apk:
1 2 3 4 5 6 7 8 9 10 11 12 void sendSystemPackageAppearedBroadcasts () { final int packageCount = (appearedChildPackages != null ) ? appearedChildPackages.size() : 0 ; for (int i = 0 ; i < packageCount; i++) { PackageInstalledInfo installedInfo = appearedChildPackages.valueAt(i); for (int userId : installedInfo.newUsers) { sendPackageAddedForUser(installedInfo.name, true , UserHandle.getAppId(installedInfo.uid), userId); } } }
5.2.1.4.1 sendPackageAddedForUser(of pms) 1 2 3 4 5 6 7 private void sendPackageAddedForUser (String packageName, PackageSetting pkgSetting, int userId) { final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting); sendPackageAddedForUser(packageName, isSystem, pkgSetting.appId, userId); }
5.2.1.4.2 sendPackageAddedForUser(of pms) 核心方法,这里的 boolean isSystem 传入的是 true:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private void sendPackageAddedForUser (String packageName, boolean isSystem, int appId, int userId) { Bundle extras = new Bundle(1 ); extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, appId)); sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 , null , null , new int [] {userId}); try { IActivityManager am = ActivityManagerNative.getDefault(); if (isSystem && am.isUserRunning(userId, 0 )) { Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED) .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) .setPackage(packageName); am.broadcastIntent(null , bcIntent, null , null , 0 , null , null , null , android.app.AppOpsManager.OP_NONE, null , false , false , userId); } } catch (RemoteException e) { Slog.w(TAG, "Unable to bootstrap installed package" , e); } }
5.2.2 isPackageDeviceAdmin 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 private boolean isPackageDeviceAdmin (String packageName, int userId) { IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface( ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); try { if (dpm != null ) { final ComponentName deviceOwnerComponentName = dpm.getDeviceOwnerComponent( false ); final String deviceOwnerPackageName = deviceOwnerComponentName == null ? null : deviceOwnerComponentName.getPackageName(); if (packageName.equals(deviceOwnerPackageName)) { return true ; } int [] users; if (userId == UserHandle.USER_ALL) { users = sUserManager.getUserIds(); } else { users = new int []{userId}; } for (int i = 0 ; i < users.length; ++i) { if (dpm.packageHasActiveAdmins(packageName, users[i])) { return true ; } } } } catch (RemoteException e) { } return false ; }
5.2.3 isUpdatedSystemApp 1 2 3 private static boolean isUpdatedSystemApp (PackageSetting ps) { return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ; }
5.2.4 freezePackageForInstall 进入冻结状态!1 2 3 4 5 6 7 8 9 public PackageFreezer freezePackageForInstall (String packageName, int userId, int installFlags, String killReason) { if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0 ) { return new PackageFreezer(); } else { return freezePackage(packageName, userId, killReason); } }
5.2.4.1 freezePackage 看代码是创建了一个 PackageFreezer 实例:
1 2 3 4 public PackageFreezer freezePackage (String packageName, int userId, String killReason) { return new PackageFreezer(packageName, userId, killReason); }
5.2.4.2 new PackageFreezer PackageFreezer 是一个冻结对象,在创建它的时候就会执行冻结操作!
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 private class PackageFreezer implements AutoCloseable { private final String mPackageName; private final PackageFreezer[] mChildren; private final boolean mWeFroze; private final AtomicBoolean mClosed = new AtomicBoolean(); private final CloseGuard mCloseGuard = CloseGuard.get(); public PackageFreezer () { mPackageName = null ; mChildren = null ; mWeFroze = false ; mCloseGuard.open("close" ); } public PackageFreezer (String packageName, int userId, String killReason) { synchronized (mPackages) { mPackageName = packageName; mWeFroze = mFrozenPackages.add(mPackageName); final PackageSetting ps = mSettings.mPackages.get(mPackageName); if (ps != null ) { killApplication(ps.name, ps.appId, userId, killReason); } final PackageParser.Package p = mPackages.get(packageName); if (p != null && p.childPackages != null ) { final int N = p.childPackages.size(); mChildren = new PackageFreezer[N]; for (int i = 0 ; i < N; i++) { mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName, userId, killReason); } } else { mChildren = null ; } } mCloseGuard.open("close" ); } ... ... ... }
在 pms 的内部,有一个集合:
1 2 @GuardedBy ("mPackages" )final ArraySet<String> mFrozenPackages = new ArraySet<>();
用于保存所有的处于冻结状态的 package!
5.3 deletePackageLIF 接着进入卸载的第三个阶段,我们来回归下参数:
boolean deleteCodeAndResources:表示是否删除 apk 和资源,这里传入的是 true;
int flags:卸载的 flags,传入 deleteFlags | REMOVE_CHATTY;
boolean writeSettings:是否持久化处理的数据,这里传入的是 true;
PackageParser.Package replacingPackage:用于取代的 pkg,这里传入的是 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 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 private boolean deletePackageLIF (String packageName, UserHandle user, boolean deleteCodeAndResources, int [] allUserHandles, int flags, PackageRemovedInfo outInfo, boolean writeSettings, PackageParser.Package replacingPackage) { if (packageName == null ) { Slog.w(TAG, "Attempt to delete null packageName." ); return false ; } if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user); PackageSetting ps; synchronized (mPackages) { ps = mSettings.mPackages.get(packageName); if (ps == null ) { Slog.w(TAG, "Package named '" + packageName + "' doesn't exist." ); return false ; } if (ps.parentPackageName != null && (!isSystemApp(ps) || (flags & PackageManager.DELETE_SYSTEM_APP) != 0 )) { if (DEBUG_REMOVE) { Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:" + ((user == null ) ? UserHandle.USER_ALL : user)); } final int removedUserId = (user != null ) ? user.getIdentifier() : UserHandle.USER_ALL; if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) { return false ; } markPackageUninstalledForUserLPw(ps, user); scheduleWritePackageRestrictionsLocked(user); return true ; } } if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0 ) && user != null && user.getIdentifier() != UserHandle.USER_ALL)) { markPackageUninstalledForUserLPw(ps, user); if (!isSystemApp(ps)) { boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName); if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) { if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users" ); if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) { return false ; } scheduleWritePackageRestrictionsLocked(user); return true ; } else { if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete" ); ps.setInstalled(true , user.getIdentifier()); } } else { if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app" ); if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) { return false ; } scheduleWritePackageRestrictionsLocked(user); return true ; } } if (ps.childPackageNames != null && outInfo != null ) { synchronized (mPackages) { final int childCount = ps.childPackageNames.size(); outInfo.removedChildPackages = new ArrayMap<>(childCount); for (int i = 0 ; i < childCount; i++) { String childPackageName = ps.childPackageNames.get(i); PackageRemovedInfo childInfo = new PackageRemovedInfo(); childInfo.removedPackage = childPackageName; outInfo.removedChildPackages.put(childPackageName, childInfo); PackageSetting childPs = mSettings.peekPackageLPr(childPackageName); if (childPs != null ) { childInfo.origUsers = childPs.queryInstalledUsers(allUserHandles, true ); } } } } boolean ret = false ; if (isSystemApp(ps)) { if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name); ret = deleteSystemPackageLIF(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings); } else { if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name); ret = deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles, outInfo, writeSettings, replacingPackage); } if (outInfo != null ) { outInfo.removedForAllUsers = mPackages.get(ps.name) == null ; if (outInfo.removedChildPackages != null ) { synchronized (mPackages) { final int childCount = outInfo.removedChildPackages.size(); for (int i = 0 ; i < childCount; i++) { PackageRemovedInfo childInfo = outInfo.removedChildPackages.valueAt(i); if (childInfo != null ) { childInfo.removedForAllUsers = mPackages.get( childInfo.removedPackage) == null ; } } } } if (isSystemApp(ps)) { synchronized (mPackages) { PackageSetting updatedPs = mSettings.peekPackageLPr(ps.name); final int childCount = (updatedPs.childPackageNames != null ) ? updatedPs.childPackageNames.size() : 0 ; for (int i = 0 ; i < childCount; i++) { String childPackageName = updatedPs.childPackageNames.get(i); if (outInfo.removedChildPackages == null || outInfo.removedChildPackages.indexOfKey(childPackageName) < 0 ) { PackageSetting childPs = mSettings.peekPackageLPr(childPackageName); if (childPs == null ) { continue ; } PackageInstalledInfo installRes = new PackageInstalledInfo(); installRes.name = childPackageName; installRes.newUsers = childPs.queryInstalledUsers(allUserHandles, true ); installRes.pkg = mPackages.get(childPackageName); installRes.uid = childPs.pkg.applicationInfo.uid; if (outInfo.appearedChildPackages == null ) { outInfo.appearedChildPackages = new ArrayMap<>(); } outInfo.appearedChildPackages.put(childPackageName, installRes); } } } } } return ret; }
到这里,这一阶段就分析结束了!
5.3.1 clearPackageStateForUserLIF 清理数据,可以看到这个方法里面执行的操作有很多:清楚数据等等:
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 private boolean clearPackageStateForUserLIF (PackageSetting ps, int userId, PackageRemovedInfo outInfo) { final PackageParser.Package pkg; synchronized (mPackages) { pkg = mPackages.get(ps.name); } final int [] userIds = (userId == UserHandle.USER_ALL) ? sUserManager.getUserIds() : new int [] {userId}; for (int nextUserId : userIds) { if (DEBUG_REMOVE) { Slog.d(TAG, "Updating package:" + ps.name + " install state for user:" + nextUserId); } destroyAppDataLIF(pkg, userId, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); destroyAppProfilesLIF(pkg, userId); removeKeystoreDataIfNeeded(nextUserId, ps.appId); schedulePackageCleaning(ps.name, nextUserId, false ); synchronized (mPackages) { if (clearPackagePreferredActivitiesLPw(ps.name, nextUserId)) { scheduleWritePackageRestrictionsLocked(nextUserId); } resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, nextUserId); } } if (outInfo != null ) { outInfo.removedPackage = ps.name; outInfo.removedAppId = ps.appId; outInfo.removedUsers = userIds; } return true ; }
5.3.2 markPackageUninstalledForUserLPw 修改在该 user 下的使用状态为 no install 的状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void markPackageUninstalledForUserLPw (PackageSetting ps, UserHandle user) { final int [] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL) ? sUserManager.getUserIds() : new int [] {user.getIdentifier()}; for (int nextUserId : userIds) { if (DEBUG_REMOVE) { Slog.d(TAG, "Marking package:" + ps.name + " uninstalled for user:" + nextUserId); } ps.setUserState(nextUserId, 0 , COMPONENT_ENABLED_STATE_DEFAULT, false , true , true , false , false , null , null , null , false , ps.readUserState(nextUserId).domainVerificationStatus, 0 ); } }
方法很简单,就不多说了!
5.3.3 shouldKeepUninstalledPackageLPr 1 2 3 private boolean shouldKeepUninstalledPackageLPr (String packageName) { return mKeepUninstalledPackages != null && mKeepUninstalledPackages.contains(packageName); }
6 PackageManagerService 接下来,我们分别分析下 sys app 和 data app 的卸载过程:
6.1 deleteSystemPackageLIF 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 private boolean deleteSystemPackageLIF (PackageParser.Package deletedPkg, PackageSetting deletedPs, int [] allUserHandles, int flags, PackageRemovedInfo outInfo, boolean writeSettings) { if (deletedPs.parentPackageName != null ) { Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName); return false ; } final boolean applyUserRestrictions = (allUserHandles != null ) && (outInfo.origUsers != null ); final PackageSetting disabledPs; synchronized (mPackages) { disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPs.name); } if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName + " disabledPs=" + disabledPs); if (disabledPs == null ) { Slog.w(TAG, "Attempt to delete unknown system package " + deletedPkg.packageName); return false ; } else if (DEBUG_REMOVE) { Slog.d(TAG, "Deleting system pkg from data partition" ); } if (DEBUG_REMOVE) { if (applyUserRestrictions) { Slog.d(TAG, "Remembering install states:" ); for (int userId : allUserHandles) { final boolean finstalled = ArrayUtils.contains(outInfo.origUsers, userId); Slog.d(TAG, " u=" + userId + " inst=" + finstalled); } } } outInfo.isRemovedPackageSystemUpdate = true ; if (outInfo.removedChildPackages != null ) { final int childCount = (deletedPs.childPackageNames != null ) ? deletedPs.childPackageNames.size() : 0 ; for (int i = 0 ; i < childCount; i++) { String childPackageName = deletedPs.childPackageNames.get(i); if (disabledPs.childPackageNames != null && disabledPs.childPackageNames .contains(childPackageName)) { PackageRemovedInfo childInfo = outInfo.removedChildPackages.get( childPackageName); if (childInfo != null ) { childInfo.isRemovedPackageSystemUpdate = true ; } } } } if (disabledPs.versionCode < deletedPs.versionCode) { flags &= ~PackageManager.DELETE_KEEP_DATA; } else { flags |= PackageManager.DELETE_KEEP_DATA; } boolean ret = deleteInstalledPackageLIF(deletedPs, true , flags, allUserHandles, outInfo, writeSettings, disabledPs.pkg); if (!ret) { return false ; } synchronized (mPackages) { enableSystemPackageLPw(disabledPs.pkg); removeNativeBinariesLI(deletedPs); } if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); int parseFlags = mDefParseFlags | PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; if (locationIsPrivileged(disabledPs.codePath)) { parseFlags |= PackageParser.PARSE_IS_PRIVILEGED; } final PackageParser.Package newPkg; try { newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, SCAN_NO_PATHS, 0 , null ); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " + e.getMessage()); return false ; } try { updateSharedLibrariesLPw(newPkg, null ); } catch (PackageManagerException e) { Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage()); } prepareAppDataAfterInstallLIF(newPkg); synchronized (mPackages) { PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); ps.getPermissionsState().copyFrom(deletedPs.getPermissionsState()); updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); if (applyUserRestrictions) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall" ); } for (int userId : allUserHandles) { final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId); if (DEBUG_REMOVE) { Slog.d(TAG, " user " + userId + " => " + installed); } ps.setInstalled(installed, userId); mSettings.writeRuntimePermissionsForUserLPr(userId, false ); } mSettings.writeAllUsersPackageRestrictionsLPr(); } if (writeSettings) { mSettings.writeLPr(); } } return true ; }
整个逻辑很详细了,不多说了!!
6.1.1 enableSystemPackageLPw 恢复 sys app 的安装信息!
1 2 3 4 5 6 7 8 9 10 private void enableSystemPackageLPw (PackageParser.Package pkg) { mSettings.enableSystemPackageLPw(pkg.packageName); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); mSettings.enableSystemPackageLPw(childPkg.packageName); } }
不多说了!
6.1.1.1 Settings.enableSystemPackageLPw 核心方法是在 Settings 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 PackageSetting enableSystemPackageLPw (String name) { PackageSetting p = mDisabledSysPackages.get(name); if (p == null ) { Log.w(PackageManagerService.TAG, "Package " + name + " is not disabled" ); return null ; } if ((p.pkg != null ) && (p.pkg.applicationInfo != null )) { p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath, p.legacyNativeLibraryPathString, p.primaryCpuAbiString, p.secondaryCpuAbiString, p.cpuAbiOverrideString, p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags, p.parentPackageName, p.childPackageNames); mDisabledSysPackages.remove(name); return ret; }
继续分析!
6.1.2 removeNativeBinariesLI 移除本地库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void removeNativeBinariesLI (PackageSetting ps) { if (ps != null ) { NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString); final int childCount = (ps.childPackageNames != null ) ? ps.childPackageNames.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageSetting childPs = null ; synchronized (mPackages) { childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i)); } if (childPs != null ) { NativeLibraryHelper.removeNativeBinariesLI(childPs .legacyNativeLibraryPathString); } } } }
核心是通过 NativeLibraryHelper 的相关接口来移除的,这里就不过多分析了!
6.1.3 locationIsPrivileged 判断是否是 pri app:1 2 3 4 5 6 7 8 9 10 11 static boolean locationIsPrivileged (File path) { try { final String privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app" ) .getCanonicalPath(); return path.getCanonicalPath().startsWith(privilegedAppDir); } catch (IOException e) { Slog.e(TAG, "Unable to access code path " + path); } return false ; }
不多说了!!
6.1.4 updateSharedLibrariesLPw 更新共享库文件:
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 private void updateSharedLibrariesLPw (PackageParser.Package pkg, PackageParser.Package changingLib) throws PackageManagerException { if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null ) { final ArraySet<String> usesLibraryFiles = new ArraySet<>(); int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0 ; for (int i=0 ; i<N; i++) { final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesLibraries.get(i)); if (file == null ) { throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY, "Package " + pkg.packageName + " requires unavailable shared library " + pkg.usesLibraries.get(i) + "; failing!" ); } addSharedLibraryLPw(usesLibraryFiles, file, changingLib); } N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0 ; for (int i=0 ; i<N; i++) { final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i)); if (file == null ) { Slog.w(TAG, "Package " + pkg.packageName + " desires unavailable shared library " + pkg.usesOptionalLibraries.get(i) + "; ignoring!" ); } else { addSharedLibraryLPw(usesLibraryFiles, file, changingLib); } } N = usesLibraryFiles.size(); if (N > 0 ) { pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[N]); } else { pkg.usesLibraryFiles = null ; } } }
PackageParser.Package 内有如下的集合,表示该 pkg 依赖的共享库的名称:1 2 public ArrayList<String> usesLibraries = null ;public ArrayList<String> usesOptionalLibraries = null ;
同时也有下面的集合,保存了依赖的所有的共享库的路径:1 public String[] usesLibraryFiles = null ;
不多说了!
6.1.4.1 addSharedLibraryLPw 参数 PackageParser.Package changingLib 表示我们改变了共享库的定义 apk,那么我们要将新的 apk 传进来,作为新的依赖!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private void addSharedLibraryLPw (ArraySet<String> usesLibraryFiles, SharedLibraryEntry file, PackageParser.Package changingLib) { if (file.path != null ) { usesLibraryFiles.add(file.path); return ; } PackageParser.Package p = mPackages.get(file.apk); if (changingLib != null && changingLib.packageName.equals(file.apk)) { if (p == null || p.packageName.equals(changingLib.packageName)) { p = changingLib; } } if (p != null ) { usesLibraryFiles.addAll(p.getAllCodePaths()); } }
不多说了!
6.1.5 prepareAppDataAfterInstallLIF 准备数据目录!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 prepareAppDataAfterInstallLIF (PackageParser.Package pkg) { final PackageSetting ps; synchronized (mPackages) { ps = mSettings.mPackages.get(pkg.packageName); mSettings.writeKernelMappingLPr(ps); } final UserManager um = mContext.getSystemService(UserManager.class); UserManagerInternal umInternal = getUserManagerInternal(); for (UserInfo user : um.getUsers()) { final int flags; if (umInternal.isUserUnlockingOrUnlocked(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { flags = StorageManager.FLAG_STORAGE_DE; } else { continue ; } if (ps.getInstalled(user.id)) { prepareAppDataLIF(pkg, user.id, flags); } } }
继续分析:
6.1.5.1 prepareAppDataLIF 这个方法会对 pkg 以及其 child pkg 准备目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 private void prepareAppDataLIF (PackageParser.Package pkg, int userId, int flags) { if (pkg == null ) { Slog.wtf(TAG, "Package was null!" , new Throwable()); return ; } prepareAppDataLeafLIF(pkg, userId, flags); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); } }
继续分析:
6.1.5.2 prepareAppDataLeafLIF 该方法是核心的方法:
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 private void prepareAppDataLeafLIF (PackageParser.Package pkg, int userId, int flags) { if (DEBUG_APP_DATA) { Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x" + Integer.toHexString(flags)); } final String volumeUuid = pkg.volumeUuid; final String packageName = pkg.packageName; final ApplicationInfo app = pkg.applicationInfo; final int appId = UserHandle.getAppId(app.uid); Preconditions.checkNotNull(app.seinfo); try { mInstaller.createAppData(volumeUuid, packageName, userId, flags, appId, app.seinfo, app.targetSdkVersion); } catch (InstallerException e) { if (app.isSystemApp()) { logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName + ", but trying to recover: " + e); destroyAppDataLeafLIF(pkg, userId, flags); try { mInstaller.createAppData(volumeUuid, packageName, userId, flags, appId, app.seinfo, app.targetSdkVersion); logCriticalInfo(Log.DEBUG, "Recovery succeeded!" ); } catch (InstallerException e2) { logCriticalInfo(Log.DEBUG, "Recovery failed!" ); } } else { Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e); } } if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 ) { try { final long ceDataInode = mInstaller.getAppDataInode(volumeUuid, packageName, userId, StorageManager.FLAG_STORAGE_CE); synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null ) { ps.setCeDataInode(ceDataInode, userId); } } } catch (InstallerException e) { Slog.e(TAG, "Failed to find inode for " + packageName + ": " + e); } } prepareAppDataContentsLeafLIF(pkg, userId, flags); }
继续分析:
6.1.5.3 prepareAppDataContentsLeafLIF 为 native libs 创建链接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void prepareAppDataContentsLeafLIF (PackageParser.Package pkg, int userId, int flags) { final String volumeUuid = pkg.volumeUuid; final String packageName = pkg.packageName; final ApplicationInfo app = pkg.applicationInfo; if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 ) { if (app.primaryCpuAbi != null && !VMRuntime.is64BitAbi(app.primaryCpuAbi)) { final String nativeLibPath = app.nativeLibraryDir; try { mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName, nativeLibPath, userId); } catch (InstallerException e) { Slog.e(TAG, "Failed to link native for " + packageName + ": " + e); } } } }
先分析到这里!
6.2 deleteInstalledPackageLIF 卸载三方应用,或者覆盖更新的 sys app,那么我们调用的是该方法:
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 private boolean deleteInstalledPackageLIF (PackageSetting ps, boolean deleteCodeAndResources, int flags, int [] allUserHandles, PackageRemovedInfo outInfo, boolean writeSettings, PackageParser.Package replacingPackage) { synchronized (mPackages) { if (outInfo != null ) { outInfo.uid = ps.appId; } if (outInfo != null && outInfo.removedChildPackages != null ) { final int childCount = (ps.childPackageNames != null ) ? ps.childPackageNames.size() : 0 ; for (int i = 0 ; i < childCount; i++) { String childPackageName = ps.childPackageNames.get(i); PackageSetting childPs = mSettings.mPackages.get(childPackageName); if (childPs == null ) { return false ; } PackageRemovedInfo childInfo = outInfo.removedChildPackages.get( childPackageName); if (childInfo != null ) { childInfo.uid = childPs.appId; } } } } removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings); final int childCount = (ps.childPackageNames != null ) ? ps.childPackageNames.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageSetting childPs; synchronized (mPackages) { childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i)); } if (childPs != null ) { PackageRemovedInfo childOutInfo = (outInfo != null && outInfo.removedChildPackages != null ) ? outInfo.removedChildPackages.get(childPs.name) : null ; final int deleteFlags = (flags & DELETE_KEEP_DATA) != 0 && (replacingPackage != null && !replacingPackage.hasChildPackage(childPs.name)) ? flags & ~DELETE_KEEP_DATA : flags; removePackageDataLIF(childPs, allUserHandles, childOutInfo, deleteFlags, writeSettings); } } if (ps.parentPackageName == null ) { if (deleteCodeAndResources && (outInfo != null )) { outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps), ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps)); if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args); } } return true ; }
6.2.1 removePackageDataLIF 删除 package 的数据!
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 private void removePackageDataLIF (PackageSetting ps, int [] allUserHandles, PackageRemovedInfo outInfo, int flags, boolean writeSettings) { String packageName = ps.name; if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps); final PackageParser.Package deletedPkg; final PackageSetting deletedPs; synchronized (mPackages) { deletedPkg = mPackages.get(packageName); deletedPs = mSettings.mPackages.get(packageName); if (outInfo != null ) { outInfo.removedPackage = packageName; outInfo.removedUsers = deletedPs != null ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true ) : null ; } } removePackageLI(ps, (flags & REMOVE_CHATTY) != 0 ); if ((flags & PackageManager.DELETE_KEEP_DATA) == 0 ) { final PackageParser.Package resolvedPkg; if (deletedPkg != null ) { resolvedPkg = deletedPkg; } else { resolvedPkg = new PackageParser.Package(ps.name); resolvedPkg.setVolumeUuid(ps.volumeUuid); } destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); destroyAppProfilesLIF(resolvedPkg, UserHandle.USER_ALL); if (outInfo != null ) { outInfo.dataRemoved = true ; } schedulePackageCleaning(packageName, UserHandle.USER_ALL, true ); } synchronized (mPackages) { if (deletedPs != null ) { if ((flags & PackageManager.DELETE_KEEP_DATA) == 0 ) { clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); clearDefaultBrowserIfNeeded(packageName); if (outInfo != null ) { mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); outInfo.removedAppId = mSettings.removePackageLPw(packageName); } updatePermissionsLPw(deletedPs.name, null , 0 ); if (deletedPs.sharedUser != null ) { for (int userId : UserManagerService.getInstance().getUserIds()) { final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs, userId); if (userIdToKill == UserHandle.USER_ALL || userIdToKill >= UserHandle.USER_SYSTEM) { mHandler.post(new Runnable() { @Override public void run () { killApplication(deletedPs.name, deletedPs.appId, KILL_APP_REASON_GIDS_CHANGED); } }); break ; } } } clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL); } if (allUserHandles != null && outInfo != null && outInfo.origUsers != null ) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across downgrade" ); } for (int userId : allUserHandles) { final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId); if (DEBUG_REMOVE) { Slog.d(TAG, " user " + userId + " => " + installed); } ps.setInstalled(installed, userId); } } } if (writeSettings) { mSettings.writeLPr(); } } if (outInfo != null ) { removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId); } }
这里我们详细的分析了整个流程!!
6.2.1.1 removePackageLI 移除 PackageSetting 对应的扫描数据:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void removePackageLI (PackageSetting ps, boolean chatty) { if (DEBUG_INSTALL) { if (chatty) Log.d(TAG, "Removing package " + ps.name); } synchronized (mPackages) { mPackages.remove(ps.name); final PackageParser.Package pkg = ps.pkg; if (pkg != null ) { cleanPackageDataStructuresLILPw(pkg, chatty); } } }
这个就不多说了!!
6.2.1.1.1 cleanPackageDataStructuresLILPw 用于删除 apk 的四大组件和共享库数据: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 void cleanPackageDataStructuresLILPw (PackageParser.Package pkg, boolean chatty) { int N = pkg.providers.size(); StringBuilder r = null ; int i; for (i=0 ; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); mProviders.removeProvider(p); if (p.info.authority == null ) { continue ; } String names[] = p.info.authority.split(";" ); for (int j = 0 ; j < names.length; j++) { if (mProvidersByAuthority.get(names[j]) == p) { mProvidersByAuthority.remove(names[j]); if (DEBUG_REMOVE) { if (chatty) Log.d(TAG, "Unregistered content provider: " + names[j] + ", className = " + p.info.name + ", isSyncable = " + p.info.isSyncable); } } } if (DEBUG_REMOVE && chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(p.info.name); } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r); } N = pkg.services.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Service s = pkg.services.get(i); mServices.removeService(s); if (chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(s.info.name); } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r); } N = pkg.receivers.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Activity a = pkg.receivers.get(i); mReceivers.removeActivity(a, "receiver" ); if (DEBUG_REMOVE && chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(a.info.name); } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r); } N = pkg.activities.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); mActivities.removeActivity(a, "activity" ); if (DEBUG_REMOVE && chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(a.info.name); } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r); } N = pkg.permissions.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Permission p = pkg.permissions.get(i); BasePermission bp = mSettings.mPermissions.get(p.info.name); if (bp == null ) { bp = mSettings.mPermissionTrees.get(p.info.name); } if (bp != null && bp.perm == p) { bp.perm = null ; if (DEBUG_REMOVE && chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(p.info.name); } } if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0 ) { ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(p.info.name); if (appOpPkgs != null ) { appOpPkgs.remove(pkg.packageName); } } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r); } N = pkg.requestedPermissions.size(); r = null ; for (i=0 ; i<N; i++) { String perm = pkg.requestedPermissions.get(i); BasePermission bp = mSettings.mPermissions.get(perm); if (bp != null && (bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0 ) { ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(perm); if (appOpPkgs != null ) { appOpPkgs.remove(pkg.packageName); if (appOpPkgs.isEmpty()) { mAppOpPermissionPackages.remove(perm); } } } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r); } N = pkg.instrumentation.size(); r = null ; for (i=0 ; i<N; i++) { PackageParser.Instrumentation a = pkg.instrumentation.get(i); mInstrumentation.remove(a.getComponentName()); if (DEBUG_REMOVE && chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(a.info.name); } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r); } r = null ; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0 ) { if (pkg.libraryNames != null ) { for (i=0 ; i<pkg.libraryNames.size(); i++) { String name = pkg.libraryNames.get(i); SharedLibraryEntry cur = mSharedLibraries.get(name); if (cur != null && cur.apk != null && cur.apk.equals(pkg.packageName)) { mSharedLibraries.remove(name); if (DEBUG_REMOVE && chatty) { if (r == null ) { r = new StringBuilder(256 ); } else { r.append(' ' ); } r.append(name); } } } } } if (r != null ) { if (DEBUG_REMOVE) Log.d(TAG, " Libraries: " + r); } }
该阶段的逻辑比较简单,不多说了!
6.2.1.2 destroyAppDataLIF ->[Leaf] 1 2 3 4 5 6 7 8 9 10 11 12 13 private void destroyAppDataLIF (PackageParser.Package pkg, int userId, int flags) { if (pkg == null ) { Slog.wtf(TAG, "Package was null!" , new Throwable()); return ; } destroyAppDataLeafLIF(pkg, userId, flags); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { destroyAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); } }
继续看:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void destroyAppDataLeafLIF (PackageParser.Package pkg, int userId, int flags) { final PackageSetting ps; synchronized (mPackages) { ps = mSettings.mPackages.get(pkg.packageName); } for (int realUserId : resolveUserIds(userId)) { final long ceDataInode = (ps != null ) ? ps.getCeDataInode(realUserId) : 0 ; try { mInstaller.destroyAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags, ceDataInode); } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); } } }
这里使用了 PackageSetting.getCeDataInode 方法:
1 2 3 long getCeDataInode (int userId) { return readUserState(userId).ceDataInode; }
该方法返回的是 PackageUserState.ceDataInode 的值!
6.2.1.4 schedulePackageCleaning 1 2 3 4 5 6 7 8 9 10 11 12 13 void schedulePackageCleaning (String packageName, int userId, boolean andCode) { final Message msg = mHandler.obtainMessage(START_CLEANING_PACKAGE, userId, andCode ? 1 : 0 , packageName); if (mSystemReady) { msg.sendToTarget(); } else { if (mPostSystemReadyMessages == null ) { mPostSystemReadyMessages = new ArrayList<>(); } mPostSystemReadyMessages.add(msg); } }
6.2.1.4.1 Packagehandler.doHandleMessage[START_CLEANING_PACKAGE] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 case START_CLEANING_PACKAGE: { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); final String packageName = (String)msg.obj; final int userId = msg.arg1; final boolean andCode = msg.arg2 != 0 ; synchronized (mPackages) { if (userId == UserHandle.USER_ALL) { int [] users = sUserManager.getUserIds(); for (int user : users) { mSettings.addPackageToCleanLPw( new PackageCleanItem(user, packageName, andCode)); } } else { mSettings.addPackageToCleanLPw( new PackageCleanItem(userId, packageName, andCode)); } } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); startCleaningPackages(); } break ;
6.2.1.4.2 startCleaningPackages 执行扩展存储清理操作:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void startCleaningPackages () { if (!isExternalMediaAvailable()) { return ; } synchronized (mPackages) { if (mSettings.mPackagesToBeCleaned.isEmpty()) { return ; } } Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE); intent.setComponent(DEFAULT_CONTAINER_COMPONENT); IActivityManager am = ActivityManagerNative.getDefault(); if (am != null ) { try { am.startService(null , intent, null , mContext.getOpPackageName(), UserHandle.USER_SYSTEM); } catch (RemoteException e) { } } }
进入 DefaultContainerService.onHandleIntent 方法:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override protected void onHandleIntent (Intent intent) { if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) { final IPackageManager pm = IPackageManager.Stub.asInterface( ServiceManager.getService("package" )); PackageCleanItem item = null ; try { while ((item = pm.nextPackageToClean(item)) != null ) { final UserEnvironment userEnv = new UserEnvironment(item.userId); eraseFiles(userEnv.buildExternalStorageAppDataDirs(item.packageName)); eraseFiles(userEnv.buildExternalStorageAppMediaDirs(item.packageName)); if (item.andCode) { eraseFiles(userEnv.buildExternalStorageAppObbDirs(item.packageName)); } } } catch (RemoteException e) { } } }
这里的逻辑就不多说了!
6.2.1.5 Settings.removePackageLPw 移除该 pkg 的安装信息:PackageSetting!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int removePackageLPw (String name) { final PackageSetting p = mPackages.get(name); if (p != null ) { mPackages .remove(name); removeInstallerPackageStatus(name); if (p.sharedUser != null ) { p.sharedUser.removePackage(p); if (p.sharedUser.packages.size() == 0 ) { mSharedUsers.remove(p.sharedUser.name); removeUserIdLPw(p.sharedUser.userId); return p.sharedUser.userId; } } else { removeUserIdLPw(p.appId); return p.appId; } } return -1 ; }
该方法最后会返回 pkg 的 appID!
6.2.1.5.1 Settings.removeInstallerPackageStatus 如果该 pkg 是 installer,那么1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private void removeInstallerPackageStatus (String packageName) { if (!mInstallerPackages.contains(packageName)) { return ; } for (int i = 0 ; i < mPackages.size(); i++) { final PackageSetting ps = mPackages.valueAt(i); final String installerPackageName = ps.getInstallerPackageName(); if (installerPackageName != null && installerPackageName.equals(packageName)) { ps.setInstallerPackageName(null ); ps.isOrphaned = true ; } } mInstallerPackages.remove(packageName); }
不多说了!!
6.2.2 createInstallArgsForExisting - 用于卸载 apk 这里是针对已存在的应用创建一个 InstallArgs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private InstallArgs createInstallArgsForExisting (int installFlags, String codePath, String resourcePath, String[] instructionSets) { final boolean isInAsec; if (installOnExternalAsec(installFlags)) { isInAsec = true ; } else if (installForwardLocked(installFlags) && !codePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) { isInAsec = true ; } else { isInAsec = false ; } if (isInAsec) { return new AsecInstallArgs(codePath, instructionSets, installOnExternalAsec(installFlags), installForwardLocked(installFlags)); } else { return new FileInstallArgs(codePath, resourcePath, instructionSets); } }
这里又回到了 5.5.3.1 的 FileInstallArgs 的相关创建!
6.2.2.1 FileInstallArgs 6.2.2.1.1 new FileInstallArgs 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 class FileInstallArgs extends InstallArgs { private File codeFile; private File resourceFile; FileInstallArgs(InstallParams params) { super (params.origin, params.move, params.observer, params.installFlags, params.installerPackageName, params.volumeUuid, params.getUser(), null , params.packageAbiOverride, params.grantedRuntimePermissions, params.traceMethod, params.traceCookie, params.certificates); if (isFwdLocked()) { throw new IllegalArgumentException("Forward locking only supported in ASEC" ); } } FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) { super (OriginInfo.fromNothing(), null , null , 0 , null , null , null , instructionSets, null , null , null , 0 , null ); this .codeFile = (codePath != null ) ? new File(codePath) : null ; this .resourceFile = (resourcePath != null ) ? new File(resourcePath) : null ; } ... ... ... }
我们看到 FileInstallArgs 有两个构造器!
一参数构造器用于创建安装过程中的 InstallArgs!
三参数构造器,用于描述一个已存在的安装,主要用于清除旧的安装,或者作为移动应用的时候的源数据,我们在 pms 开机初始化的过程中就已经看到过了!
6.2.2.1.2 doPostDeleteLI 继续来看:1 2 3 4 5 boolean doPostDeleteLI (boolean delete) { cleanUpResourcesLI(); return true ; }
继续分析:
6.2.2.1.3 cleanUpResourcesLI 继续分析:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void cleanUpResourcesLI () { List<String> allCodePaths = Collections.EMPTY_LIST; if (codeFile != null && codeFile.exists()) { try { final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0 ); allCodePaths = pkg.getAllCodePaths(); } catch (PackageParserException e) { } } cleanUp(); removeDexFiles(allCodePaths, instructionSets); }
7 remove split apk - 移除 split(模块)apk 在最上面的分析中,我们知道,如果要删除的是 split apk,那么会进入另外一个接口,这个接口和 install 的流程很类似,我们在这里做一下分析:
因为和 install 有很多相似之处,所以我省略掉一些无关紧要的代码段!!
7.1 PackageInstallerService 7.1.1 createSession(Internal) - 创建事务 创建事务:
1 2 3 4 5 6 7 8 9 @Override public int createSession (SessionParams params, String installerPackageName, int userId) { try { return createSessionInternal(params, installerPackageName, userId); } catch (IOException e) { throw ExceptionUtils.wrap(e); } }
createSession 方法调用了 createSessionInternal 方法:
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 private int createSessionInternal (SessionParams params, String installerPackageName, int userId) throws IOException { final int callingUid = Binder.getCallingUid(); mPm.enforceCrossUserPermission(callingUid, userId, true , true , "createSession" ); if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { throw new SecurityException("User restriction prevents installing" ); } if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) { params.installFlags |= PackageManager.INSTALL_FROM_ADB; } else { mAppOps.checkPackage(callingUid, installerPackageName); params.installFlags &= ~PackageManager.INSTALL_FROM_ADB; params.installFlags &= ~PackageManager.INSTALL_ALL_USERS; params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; } if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0 && mContext.checkCallingOrSelfPermission(Manifest.permission .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) { throw new SecurityException("You need the " + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission " + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag" ); } if (params.appIcon != null ) { final ActivityManager am = (ActivityManager) mContext.getSystemService( Context.ACTIVITY_SERVICE); final int iconSize = am.getLauncherLargeIconSize(); if ((params.appIcon.getWidth() > iconSize * 2 ) || (params.appIcon.getHeight() > iconSize * 2 )) { params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize, true ); } } switch (params.mode) { case SessionParams.MODE_FULL_INSTALL: case SessionParams.MODE_INHERIT_EXISTING: break ; default : throw new IllegalArgumentException("Invalid install mode: " + params.mode); } if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0 ) { if (!PackageHelper.fitsOnInternal(mContext, params.sizeBytes)) { throw new IOException("No suitable internal storage available" ); } } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ) { if (!PackageHelper.fitsOnExternal(mContext, params.sizeBytes)) { throw new IOException("No suitable external storage available" ); } } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0 ) { params.setInstallFlagsInternal(); } else { params.setInstallFlagsInternal(); final long ident = Binder.clearCallingIdentity(); try { params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params.appPackageName, params.installLocation, params.sizeBytes); } finally { Binder.restoreCallingIdentity(ident); } } final int sessionId; final PackageInstallerSession session; synchronized (mSessions) { final int activeCount = getSessionCount(mSessions, callingUid); if (activeCount >= MAX_ACTIVE_SESSIONS) { throw new IllegalStateException( "Too many active sessions for UID " + callingUid); } final int historicalCount = getSessionCount(mHistoricalSessions, callingUid); if (historicalCount >= MAX_HISTORICAL_SESSIONS) { throw new IllegalStateException( "Too many historical sessions for UID " + callingUid); } sessionId = allocateSessionIdLocked(); } final long createdMillis = System.currentTimeMillis(); File stageDir = null ; String stageCid = null ; if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0 ) { final boolean isEphemeral = (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ; stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral); } else { stageCid = buildExternalStageCid(sessionId); } session = new PackageInstallerSession(mInternalCallback, mContext, mPm, mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false , false ); synchronized (mSessions) { mSessions.put(sessionId, session); } mCallbacks.notifySessionCreated(session.sessionId, session.userId); writeSessionsAsync(); return sessionId; }
整个流程和 install 很像,我们可以大胆推测,其在移除了 split apk 后,还会把主 apk 再 install 一次!!
7.1.2 openSession - 获得事务 openSession 方法可以获得 id 对应的 PackageInstallerSession!1 2 3 4 5 6 7 8 9 @Override public IPackageInstallerSession openSession (int sessionId) { try { return openSessionInternal(sessionId); } catch (IOException e) { throw ExceptionUtils.wrap(e); } }
7.1.2.1 openSessionInternal 1 2 3 4 5 6 7 8 9 10 11 private IPackageInstallerSession openSessionInternal (int sessionId) throws IOException { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); if (session == null || !isCallingUidOwner(session)) { throw new SecurityException("Caller has no access to session " + sessionId); } session.open(); return session; } }
7.2 PackageInstallerSession 7.2.1 new PackageInstallerSession - 事务实例 创建 PackageInstallerSession,对前面的 SessionParams 再次封装!
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 public class PackageInstallerSession extends IPackageInstallerSession .Stub { public PackageInstallerSession (PackageInstallerService.InternalCallback callback, Context context, PackageManagerService pm, Looper looper, int sessionId, int userId, String installerPackageName, int installerUid, SessionParams params, long createdMillis, File stageDir, String stageCid, boolean prepared, boolean sealed) { mCallback = callback; mContext = context; mPm = pm; mHandler = new Handler(looper, mHandlerCallback); this .sessionId = sessionId; this .userId = userId; this .installerPackageName = installerPackageName; this .installerUid = installerUid; this .params = params; this .createdMillis = createdMillis; this .stageDir = stageDir; this .stageCid = stageCid; if ((stageDir == null ) == (stageCid == null )) { throw new IllegalArgumentException( "Exactly one of stageDir or stageCid stage must be set" ); } mPrepared = prepared; mSealed = sealed; DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService( Context.DEVICE_POLICY_SERVICE); final boolean isPermissionGranted = (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED); final boolean isInstallerRoot = (installerUid == Process.ROOT_UID); final boolean forcePermissionPrompt = (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0 ; mIsInstallerDeviceOwner = (dpm != null ) && dpm.isDeviceOwnerAppOnCallingUser( installerPackageName); if ((isPermissionGranted || isInstallerRoot || mIsInstallerDeviceOwner) && !forcePermissionPrompt) { mPermissionsAccepted = true ; } else { mPermissionsAccepted = false ; } final long identity = Binder.clearCallingIdentity(); try { final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE, PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); defaultContainerGid = UserHandle.getSharedAppGid(uid); } finally { Binder.restoreCallingIdentity(identity); } }
可以看到 PackageInstallerSession 除了用来表示一个 Session 之外,由于继承了 IPackageInstallerSession.Stub,因此其还可以作为服务端的桩对象,进行跨进程的通信!
7.2.2 removeSplit 1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public void removeSplit (String splitName) { if (TextUtils.isEmpty(params.appPackageName)) { throw new IllegalStateException("Must specify package name to remove a split" ); } try { createRemoveSplitMarker(splitName); } catch (IOException e) { throw ExceptionUtils.wrap(e); } }
7.2.3 createRemoveSplitMarker 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void createRemoveSplitMarker (String splitName) throws IOException { try { final String markerName = splitName + REMOVE_SPLIT_MARKER_EXTENSION; if (!FileUtils.isValidExtFilename(markerName)) { throw new IllegalArgumentException("Invalid marker: " + markerName); } final File target = new File(resolveStageDir(), markerName); target.createNewFile(); Os.chmod(target.getAbsolutePath(), 0 ); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } }
这里的 REMOVE_SPLIT_MARKER_EXTENSION 是一个字符串后缀:
1 private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed" ;
7.2.3.1 resolveStageDir 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private File resolveStageDir () throws IOException { synchronized (mLock) { if (mResolvedStageDir == null ) { if (stageDir != null ) { mResolvedStageDir = stageDir; } else { final String path = PackageHelper.getSdDir(stageCid); if (path != null ) { mResolvedStageDir = new File(path); } else { throw new IOException("Failed to resolve path to container " + stageCid); } } } return mResolvedStageDir; } }
7.2.4 commitLocked 按照流程,我们进入了 commitLocked 中:
参数 PackageInfo pkgInfo 和 ApplicationInfo appInfo 分别表示已经安装的主 apk 的信息对象!
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 private void commitLocked (PackageInfo pkgInfo, ApplicationInfo appInfo) throws PackageManagerException { if (mDestroyed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed" ); } if (!mSealed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed" ); } try { resolveStageDir(); } catch (IOException e) { throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, "Failed to resolve stage location" , e); } validateInstallLocked(pkgInfo, appInfo); Preconditions.checkNotNull(mPackageName); Preconditions.checkNotNull(mSignatures); Preconditions.checkNotNull(mResolvedBaseFile); if (!mPermissionsAccepted) { final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS); intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName()); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); try { mRemoteObserver.onUserActionRequired(intent); } catch (RemoteException ignored) { } close(); return ; } if (stageCid != null ) { final long finalSize = calculateInstalledSize(); resizeContainer(stageCid, finalSize); } if (params.mode == SessionParams.MODE_INHERIT_EXISTING) { try { final List<File> fromFiles = mResolvedInheritedFiles; final File toDir = resolveStageDir(); if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles); if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null ) { throw new IllegalStateException("mInheritedFilesBase == null" ); } if (isLinkPossible(fromFiles, toDir)) { if (!mResolvedInstructionSets.isEmpty()) { final File oatDir = new File(toDir, "oat" ); createOatDirs(mResolvedInstructionSets, oatDir); } linkFiles(fromFiles, toDir, mInheritedFilesBase); } else { copyFiles(fromFiles, toDir); } } catch (IOException e) { throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed to inherit existing install" , e); } } mInternalProgress = 0.5f ; computeProgressLocked(true ); extractNativeLibraries(mResolvedStageDir, params.abiOverride); if (stageCid != null ) { finalizeAndFixContainer(stageCid); } final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired (Intent intent) { throw new IllegalStateException(); } @Override public void onPackageInstalled (String basePackageName, int returnCode, String msg, Bundle extras) {; destroyInternal(); dispatchSessionFinished(returnCode, msg, extras); } }; final UserHandle user; if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0 ) { user = UserHandle.ALL; } else { user = new UserHandle(userId); } mRelinquished = true ; mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params, installerPackageName, installerUid, user, mCertificates); }
对于卸载 split apk 的情况:
可以看到和 install 是一样的,唯独不一样的是,会将之前已经安装的 /data/app/package-Name/ 中除了要卸载的 split apk 以外的其他 apk 拷贝到新创建的目录下,重新安装;
7.2.4.1 validateInstallLocked 校验安装有效性,这里的 mResolvedStageDir 就是前面的 /data/app/vmdl[sessionId].tmp 目录!
removeSplitList 用于表示要删除的 split apk 列表:
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 private void validateInstallLocked (PackageInfo pkgInfo, ApplicationInfo appInfo) throws PackageManagerException { mPackageName = null ; mVersionCode = -1 ; mSignatures = null ; mResolvedBaseFile = null ; mResolvedStagedFiles.clear(); mResolvedInheritedFiles.clear(); final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter); final List<String> removeSplitList = new ArrayList<>(); if (!ArrayUtils.isEmpty(removedFiles)) { for (File removedFile : removedFiles) { final String fileName = removedFile.getName(); final String splitName = fileName.substring( 0 , fileName.length() - REMOVE_SPLIT_MARKER_EXTENSION.length()); removeSplitList.add(splitName); } } final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter); if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0 ) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged" ); } final ArraySet<String> stagedSplits = new ArraySet<>(); for (File addedFile : addedFiles) { final ApkLite apk; try { apk = PackageParser.parseApkLite( addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { throw PackageManagerException.from(e); } if (!stagedSplits.add(apk.splitName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Split " + apk.splitName + " was defined multiple times" ); } if (mPackageName == null ) { mPackageName = apk.packageName; mVersionCode = apk.versionCode; } if (mSignatures == null ) { mSignatures = apk.signatures; mCertificates = apk.certificates; } assertApkConsistent(String.valueOf(addedFile), apk); final String targetName; if (apk.splitName == null ) { targetName = "base.apk" ; } else { targetName = "split_" + apk.splitName + ".apk" ; } if (!FileUtils.isValidExtFilename(targetName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Invalid filename: " + targetName); } final File targetFile = new File(mResolvedStageDir, targetName); if (!addedFile.equals(targetFile)) { addedFile.renameTo(targetFile); } if (apk.splitName == null ) { mResolvedBaseFile = targetFile; } mResolvedStagedFiles.add(targetFile); } if (removeSplitList.size() > 0 ) { for (String splitName : removeSplitList) { if (!ArrayUtils.contains(pkgInfo.splitNames, splitName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Split not found: " + splitName); } } if (mPackageName == null ) { mPackageName = pkgInfo.packageName; mVersionCode = pkgInfo.versionCode; } if (mSignatures == null ) { mSignatures = pkgInfo.signatures; } } if (params.mode == SessionParams.MODE_FULL_INSTALL) { if (!stagedSplits.contains(null )) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Full install must include a base package" ); } } else { if (appInfo == null ) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Missing existing base package for " + mPackageName); } final PackageLite existing; final ApkLite existingBase; try { existing = PackageParser.parsePackageLite(new File(appInfo.getCodePath()), 0 ); existingBase = PackageParser.parseApkLite(new File(appInfo.getBaseCodePath()), PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { throw PackageManagerException.from(e); } assertApkConsistent("Existing base" , existingBase); if (mResolvedBaseFile == null ) { mResolvedBaseFile = new File(appInfo.getBaseCodePath()); mResolvedInheritedFiles.add(mResolvedBaseFile); } if (!ArrayUtils.isEmpty(existing.splitNames)) { for (int i = 0 ; i < existing.splitNames.length; i++) { final String splitName = existing.splitNames[i]; final File splitFile = new File(existing.splitCodePaths[i]); final boolean splitRemoved = removeSplitList.contains(splitName); if (!stagedSplits.contains(splitName) && !splitRemoved) { mResolvedInheritedFiles.add(splitFile); } } } final File packageInstallDir = (new File(appInfo.getBaseCodePath())).getParentFile(); mInheritedFilesBase = packageInstallDir; final File oatDir = new File(packageInstallDir, "oat" ); if (oatDir.exists()) { final File[] archSubdirs = oatDir.listFiles(); if (archSubdirs != null && archSubdirs.length > 0 ) { final String[] instructionSets = InstructionSets.getAllDexCodeInstructionSets(); for (File archSubDir : archSubdirs) { if (!ArrayUtils.contains(instructionSets, archSubDir.getName())) { continue ; } mResolvedInstructionSets.add(archSubDir.getName()); List<File> oatFiles = Arrays.asList(archSubDir.listFiles()); if (!oatFiles.isEmpty()) { mResolvedInheritedFiles.addAll(oatFiles); } } } } } }
其实这里,我们可以看到。对于卸载 split apk 的情况,我们会收集之前安装的目录下的所有不再 remove 列表中的 apk 文件到 mResolvedInheritedFiles 集合中!