当前位置:   article > 正文

Framework篇 - APK 安装流程简介_awareframework-398.apk

awareframework-398.apk

本文源代码基于 Android 7.0。 

在 Android 系统下,我们一般会使用 "adb install -r" 命令来安装应用,此时应用会被安装到 /data/app/ 下。这篇文章,我们就简要分析 PackageManagerService 安装 APK 的中间处理过程。

 

目录:

  1. 安装流程图
  2. adb 方式安装 APK
  3. PackageManager 安装 APK

 

 

1. 安装流程图

 

 

2. adb 方式安装 APK

在进入 PackageManager 之前,我们先看下有关 adb 安装应用的内容。在 Android 中,adbd 以后台进程运行 (init 进程解析 init.rc 生成的进程,Installer 中真正干活的进程)。

当我们输入 "adb install" 命令时,/system/core/adb/ 目录下 commandline.cpp 文件会被执行,其中 adb_commandline() 函数会接受该条指令,并进行处理,这里只看 install 命令的执行:

  1. else if (!strcmp(argv[0], "install")) {
  2. if (argc < 2) return usage();
  3. if (_use_legacy_install()) {
  4. // 安装应用(legacy模式)
  5. return install_app_legacy(transport_type, serial, argc, argv);
  6. }
  7. // 安装应用
  8. return install_app(transport_type, serial, argc, argv);
  9. }
  10. ......
  11. }

这里以 legacy 模式为例:

  1. static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
  2. static const char *const DATA_DEST = "/data/local/tmp/%s";// 安装到 data 目录下时,会将 apk 先拷贝一份到该目录下
  3. static const char *const SD_DEST = "/sdcard/tmp/%s";//安装到 SD 卡上时,会将 apk 先拷贝一份到 /sdcard/tmp/ 目录下; 一般带参数 -s
  4. const char* where = DATA_DEST;
  5. int i;
  6. struct stat sb;
  7. for (i = 1; i < argc; i++) {
  8. if (!strcmp(argv[i], "-s")) {
  9. where = SD_DEST;
  10. }
  11. }
  12. // Find last APK argument.
  13. // All other arguments passed through verbatim.
  14. int last_apk = -1;
  15. for (i = argc - 1; i >= 0; i--) {
  16. const char* file = argv[i];
  17. const char* dot = strrchr(file, '.');
  18. if (dot && !strcasecmp(dot, ".apk")) {
  19. if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
  20. fprintf(stderr, "Invalid APK file: %s\n", file);
  21. return EXIT_FAILURE;
  22. }
  23. last_apk = i;
  24. break;
  25. }
  26. }
  27. if (last_apk == -1) {
  28. fprintf(stderr, "Missing APK file\n");
  29. return EXIT_FAILURE;
  30. }
  31. int result = -1;
  32. std::vector<const char*> apk_file = {argv[last_apk]};
  33. std::string apk_dest = android::base::StringPrintf(
  34. where, adb_basename(argv[last_apk]).c_str());
  35. // 我们即将安装的 apk 文件也许会在客户机上, 这里会先将该apk文件推送到系统的 /data/local/tmp/目录下
  36. if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
  37. argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
  38. // 执行 pm 脚本, 进行安装
  39. result = pm_command(transport, serial, argc, argv);
  40. cleanup_apk:
  41. // 安装过程结束后,会清掉事先拷贝的那一份apk
  42. delete_file(transport, serial, apk_dest);
  43. return result;
  44. }

由于我们使用 adb 安装的 APK 有可能会在客户机上,所以这里会先将 APK 文件拷贝一份到系统的 /data/local/tmp/ 目录下。
然后流程会去执行 pm 脚本进行安装操作。手机的端的 adbd 程序接收到客户机发送的 shell pm 命令后,会开启一个 shell 去执行 pm 脚本。pm 脚本的内容如下:

  1. # Script to start "pm" on the device, which has a very rudimentary
  2. # shell.
  3. #
  4. base=/system
  5. export CLASSPATH=$base/framework/pm.jar
  6. exec app_process $base/bin com.android.commands.pm.Pm "$@"

该脚本在系统编译时会被打包成 /system/bin/pm 可执行程序,执行 pm 可执行程序其实就是执行这段脚本。

我们知道,app_process 在系统启动过程中会去启动 Zygote 系统进程。同时,它也可以被用来启动一些其他的普通进程,比如此时的 pm。我们直接看启动 pm 时调用的 main() 函数,com.android.commands.pm.Pm::main():

  1. public static void main(String[] args) {
  2. int exitCode = 1;
  3. try {
  4. exitCode = new Pm().run(args);
  5. } catch (Exception e) {
  6. Log.e(TAG, "Error", e);
  7. System.err.println("Error: " + e);
  8. if (e instanceof RemoteException) {
  9. System.err.println(PM_NOT_RUNNING_ERR);
  10. }
  11. }
  12. System.exit(exitCode);
  13. }

创建 Pm 实例并调用它的 run() 方法:

  1. public int run(String[] args) throws RemoteException {
  2. boolean validCommand = false;
  3. if (args.length < 1) {
  4. return showUsage();
  5. }
  6. mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE));
  7. mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE));
  8. // IPackageManager实例,通过它可以调用到PackageManagerServcie中,就是binder的客户端
  9. mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
  10. // IPackageManager实例为空,即返回
  11. if (mPm == null) {
  12. System.err.println(PM_NOT_RUNNING_ERR);
  13. return 1;
  14. }
  15. // IPackageInstaller实例,它会管理android中的应用安装状态
  16. mInstaller = mPm.getPackageInstaller();
  17. mArgs = args;
  18. String op = args[0];
  19. mNextArg = 1;
  20. if ("list".equals(op)) {
  21. return runList();
  22. }
  23. if ("path".equals(op)) {
  24. return runPath();
  25. }
  26. if ("dump".equals(op)) {
  27. return runDump();
  28. }
  29. if ("install".equals(op)) {
  30. // 此处分析的是install命令,走这条分支
  31. return runInstall();
  32. }
  33. ......
  34. }

因为我们传入的是 install 命令,所以执行 runInstall() 函数;至此,安装过程就即将进入 PackageManagerService 了。同时我们也可以调用 PackageManager::installPackage() 函数安装应用,这种方式的安装与 adb install 的安装流程在进入PackageManagerService 之后,都是一样的。

 

 

3. PackageManager 安装 APK

PackageManager 的功能由 ApplicationPackageManager 实现,ApplicationPackageManager 内部持有一个指向PackageManagerService 的 mPM 对象来传递函数调用。当我们调用 PackageManager::installPackage() 时,实际调用ApplicationPackageManager 中的实现函数:

  1. @Override
  2. public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
  3. String installerPackageName) {
  4. installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
  5. installerPackageName, mContext.getUserId());
  6. }
  7. @Override
  8. public void installPackage(Uri packageURI, PackageInstallObserver observer,
  9. int flags, String installerPackageName) {
  10. installCommon(packageURI, observer, flags, installerPackageName, mContext.getUserId());
  11. }
  12. private void installCommon(Uri packageURI,
  13. PackageInstallObserver observer, int flags, String installerPackageName,
  14. int userId) {
  15. if (!"file".equals(packageURI.getScheme())) {
  16. throw new UnsupportedOperationException("Only file:// URIs are supported");
  17. }
  18. final String originPath = packageURI.getPath();
  19. try {
  20. mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
  21. userId);
  22. } catch (RemoteException e) {
  23. throw e.rethrowFromSystemServer();
  24. }
  25. }

方法中传入了一个 PackageInstallObserver 对象,它是用户用来监听 APK 安装的最后结果的。PackageInstallObserver 的定义如下:

  1. public class PackageInstallObserver {
  2. private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() {
  3. @Override
  4. public void onUserActionRequired(Intent intent) {
  5. PackageInstallObserver.this.onUserActionRequired(intent);
  6. }
  7. @Override
  8. public void onPackageInstalled(String basePackageName, int returnCode,
  9. String msg, Bundle extras) {
  10. PackageInstallObserver.this.onPackageInstalled(basePackageName, returnCode, msg,
  11. extras);
  12. }
  13. };
  14. /** {@hide} */
  15. public IPackageInstallObserver2 getBinder() {
  16. return mBinder;
  17. }
  18. public void onUserActionRequired(Intent intent) {
  19. }
  20. public void onPackageInstalled(String basePackageName, int returnCode, String msg,
  21. Bundle extras) {
  22. }
  23. }

其中,当 APK 安装结束时,系统会回调 onPackageInstalled() 接口通知用户当前 APK 安装的结果信息。

接着分析 APK 安装的流程,系统会调用 PKMS 的 installPackageAsUser() 接口,将安装流程带入到 PKMS 中:

  1. @Override
  2. public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
  3. int installFlags, String installerPackageName, int userId) {
  4. mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
  5. final int callingUid = Binder.getCallingUid();
  6. enforceCrossUserPermission(callingUid, userId,
  7. true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser");//检查调用进程的权限
  8. if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {//检查指定的用户是否被限制安装应用
  9. try {
  10. if (observer != null) {
  11. observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
  12. }
  13. } catch (RemoteException re) {
  14. }
  15. return;
  16. }
  17. if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
  18. installFlags |= PackageManager.INSTALL_FROM_ADB;
  19. } else {
  20. // Caller holds INSTALL_PACKAGES permission, so we're less strict
  21. // about installerPackageName.
  22. installFlags &= ~PackageManager.INSTALL_FROM_ADB;
  23. installFlags &= ~PackageManager.INSTALL_ALL_USERS;
  24. }
  25. UserHandle user;
  26. if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {//如果带有ISNASLL_ALL_USERS标记,则给所有用户安装
  27. user = UserHandle.ALL;
  28. } else {
  29. user = new UserHandle(userId);
  30. }
  31. // Only system components can circumvent runtime permissions when installing.
  32. if ((installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
  33. && mContext.checkCallingOrSelfPermission(Manifest.permission
  34. .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
  35. throw new SecurityException("You need the "
  36. + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
  37. + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
  38. }
  39. final File originFile = new File(originPath);
  40. final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
  41. final Message msg = mHandler.obtainMessage(INIT_COPY);//要发送INIT_COPY消息,开始拷贝需要安装的Apk
  42. final VerificationInfo verificationInfo = new VerificationInfo(
  43. null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
  44. //将安装参数信息保存到InstallParams对象中
  45. final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
  46. installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
  47. null /*packageAbiOverride*/, null /*grantedPermissions*/,
  48. null /*certificates*/);
  49. params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
  50. msg.obj = params;
  51. Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installAsUser",
  52. System.identityHashCode(msg.obj));
  53. Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
  54. System.identityHashCode(msg.obj));
  55. mHandler.sendMessage(msg);//发送消息到PackageHandler中
  56. }

首先是一些安装权限检查,之后会创建一个 InstallParams 实例,它里面封装了此次安装 APK 的各项参数。接着会发送INIT_COPY 消息到 Handler 进行处理。

这些类型的作用就是封装一次应用安装过程的一些基本信息,我们只要注意它们的使用场景即可。INIT_COPY 消息会触发 APK 文件的拷贝动作,它会由 PMS::PackageHandler 接收,而 PackageHandler 在 PkMS 初始化时会被创建。PackageHandler 主要负责这些 APK 安装消息的接收处理,我们先看 INIT_COPY 消息的处理过程:

  1. case INIT_COPY: {
  2. HandlerParams params = (HandlerParams) msg.obj;//获取Apk安装参数
  3. int idx = mPendingInstalls.size();//mPendingInstalls保存所有的需要安装的APk的安装信息
  4. if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
  5. // If a bind was already initiated we dont really
  6. // need to do anything. The pending install
  7. // will be processed later on.
  8. if (!mBound) {
  9. // 如果没有绑定DefaultContainerService服务;服务连接成功后,会置为true
  10. Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
  11. System.identityHashCode(mHandler));
  12. // If this is the only one pending we might
  13. // have to bind to the service again.
  14. if (!connectToService()) {
  15. // 异步过程.去绑定DefaultContainerService服务,绑定失败,需要报告错误信息;绑定成功后,会发送MCS_BOUND消息
  16. Slog.e(TAG, "Failed to bind to media container service");
  17. params.serviceError();
  18. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
  19. System.identityHashCode(mHandler));
  20. if (params.traceMethod != null) {
  21. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
  22. params.traceCookie);
  23. }
  24. return;
  25. } else {
  26. // 绑定服务成功后,将当前的安装参数请求保存到mPendingInstalls
  27. // Once we bind to the service, the first
  28. // pending request will be processed.
  29. mPendingInstalls.add(idx, params);
  30. }
  31. } else {
  32. mPendingInstalls.add(idx, params);
  33. // 服务已经绑定,也会将安装信息保存到mPendingInstalls中
  34. // Already bound to the service. Just make
  35. // sure we trigger off processing the first request.
  36. if (idx == 0) {//如果mPendingInstalls中只有一项内容,则立即发送MCS_BOUND消息
  37. mHandler.sendEmptyMessage(MCS_BOUND);
  38. }
  39. }
  40. break;
  41. }

mPendingInstalls 是 PackageHandler 的一个成员,它保存所有的 APK 安装的 InstallParams 对象。mBound 标识当前有没有绑定 DefaultContainerService 服务,之后的安装流程会调用它的一些方法。绑定 DCS 服务的处理由 PackageHandler::connectToService() 函数提供:

  1. static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
  2. DEFAULT_CONTAINER_PACKAGE,
  3. "com.android.defcontainer.DefaultContainerService");
  4. final private DefaultContainerConnection mDefContainerConn =
  5. new DefaultContainerConnection();
  6. class DefaultContainerConnection implements ServiceConnection {
  7. public void onServiceConnected(ComponentName name, IBinder service) {
  8. if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
  9. IMediaContainerService imcs =
  10. IMediaContainerService.Stub.asInterface(service);
  11. mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
  12. }
  13. public void onServiceDisconnected(ComponentName name) {
  14. if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
  15. }
  16. }
  17. private boolean connectToService() {
  18. if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
  19. " DefaultContainerService");
  20. Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
  21. Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
  22. if (mContext.bindServiceAsUser(service, mDefContainerConn,
  23. Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
  24. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  25. mBound = true;
  26. return true;
  27. }
  28. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  29. return false;
  30. }

如果服务绑定成功,mBound 会置为 true,并会发送 MCS_BOUND 消息,并附带 DCS 服务的 Binder 实例发送给PackageHandler。接着看 MCS_BOUND 消息的处理:

  1. case MCS_BOUND: {
  2. if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
  3. if (msg.obj != null) {
  4. mContainerService = (IMediaContainerService) msg.obj;//DefaultContainerService服务的代理
  5. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
  6. System.identityHashCode(mHandler));
  7. }
  8. if (mContainerService == null) {
  9. if (!mBound) {
  10. // 如果服务没有连接成功,则需要报告错误
  11. // Something seriously wrong since we are not bound and we are not
  12. // waiting for connection. Bail out.
  13. Slog.e(TAG, "Cannot bind to media container service");
  14. for (HandlerParams params : mPendingInstalls) {
  15. // Indicate service bind error
  16. params.serviceError();
  17. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
  18. System.identityHashCode(params));
  19. if (params.traceMethod != null) {
  20. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
  21. params.traceMethod, params.traceCookie);
  22. }
  23. return;
  24. }
  25. mPendingInstalls.clear();//情况mPendingInstalls
  26. } else {
  27. Slog.w(TAG, "Waiting to connect to media container service");
  28. }
  29. } else if (mPendingInstalls.size() > 0) {//DefaultContainerService服务连接正常
  30. HandlerParams params = mPendingInstalls.get(0);//从首部拿出需要执行的安装参数信息
  31. if (params != null) {
  32. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
  33. System.identityHashCode(params));
  34. Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
  35. if (params.startCopy()) {
  36. // 调用HandlerParrams接口,去执行apk的拷贝工作;此处是调用HandlerParrams::startCopy()
  37. // We are done... look for more work or to
  38. // go idle.
  39. if (DEBUG_SD_INSTALL) Log.i(TAG,
  40. "Checking for more work or unbind...");
  41. // Delete pending install
  42. if (mPendingInstalls.size() > 0) {
  43. //工作完成,移除mPendingInstalls首部内容,因为我们是从首部开始执行的
  44. mPendingInstalls.remove(0);
  45. }
  46. if (mPendingInstalls.size() == 0) {
  47. //如果mPendingInstalls已经没有内容,说明安装任务已经全部执行完毕,则会延迟10s后断开服务连接
  48. if (mBound) {
  49. if (DEBUG_SD_INSTALL) Log.i(TAG,
  50. "Posting delayed MCS_UNBIND");
  51. removeMessages(MCS_UNBIND);
  52. Message ubmsg = obtainMessage(MCS_UNBIND);
  53. // Unbind after a little delay, to avoid
  54. // continual thrashing.
  55. sendMessageDelayed(ubmsg, 10000);
  56. }
  57. } else {//否则,会再次发送MCS_BOUND消息,处理下一个安装请求
  58. // There are more pending requests in queue.
  59. // Just post MCS_BOUND message to trigger processing
  60. // of next pending install.
  61. if (DEBUG_SD_INSTALL) Log.i(TAG,
  62. "Posting MCS_BOUND for next work");
  63. mHandler.sendEmptyMessage(MCS_BOUND);//发送消息,处理下一个安装请求
  64. }
  65. }
  66. Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  67. }
  68. } else {
  69. // Should never happen ideally.
  70. Slog.w(TAG, "Empty queue");
  71. }
  72. break;
  73. }

mContainerService 对象保存了 DefaultContainerService 服务的 Binder 实例,它将被用来调用一些该服务中提供的方法。
如果该实例为空,则表明服务连接异常,则需要对外报告错误,并清空 mPendingInstalls 集合;如果非空,则要处理 APK 的安装请求:

  • 从 mPendingInstalls 首部取出要处理的安装参数对象,并调用 InstallParams::startCopy() 函数,开始进行 APK 的拷贝工作。
  • 如果拷贝工作完成,则会移除 mPendingInstalls 首部的对象。
  • 如果此时 mPendingInstalls 队列为空,表明所有的请求已经处理完了;则会通过发送 MCS_UNBIND 消息,延迟10s去断开与DCS 服务的连接。
  • 如果此时 mPendingInstalls 队列不为空,表明当前还有安装请求需要处理,则会再次发送 MCS_BOUND 消息,进行新一轮的安装处理流程。

因为传入的安装参数对象是 InstallParams,我们直接看它父类的 HandlerParams::startCopy() 函数:

  1. final boolean startCopy() {
  2. boolean res;
  3. try {
  4. if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
  5. if (++mRetries > MAX_RETRIES) {//会尝试安装4次,如果4次都没有安装成功,则会退出
  6. Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
  7. mHandler.sendEmptyMessage(MCS_GIVE_UP);//尝试4次后,都没有安装成功,则发送MCS_GIVE_UP消息放弃这次安装请求
  8. handleServiceError();
  9. return false;
  10. } else {
  11. handleStartCopy();
  12. res = true;
  13. }
  14. } catch (RemoteException e) {
  15. if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
  16. mHandler.sendEmptyMessage(MCS_RECONNECT);//安装出错,则发送消息MCS_RECONNECT消息重新连接
  17. res = false;
  18. }
  19. handleReturnCode();
  20. return res;
  21. }

HandlerParams::startCopy() 为 HandlerParams 的子类所共有。首先一次 APK 的安装操作总共会尝试四次,如果四次都安装失败,则会发送 MCS_GIVE_UP 消息,放弃这次安装请求,并调用子类实现的 handleServiceError() 处理错误,然后直接返回;
否则,调用子类实现的 handleStartCopy() 函数进程 copy 流程。handleStartCopy() 处理成功后,还会调用子类实现的handleReturnCode() 处理最后的结果。我们看 InstallParams::handleStartCopy() 的实现:

  1. public void handleStartCopy() throws RemoteException {
  2. int ret = PackageManager.INSTALL_SUCCEEDED;
  3. // If we're already staged, we've firmly committed to an install location
  4. if (origin.staged) {
  5. if (origin.file != null) {
  6. installFlags |= PackageManager.INSTALL_INTERNAL;
  7. installFlags &= ~PackageManager.INSTALL_EXTERNAL;
  8. } else if (origin.cid != null) {
  9. installFlags |= PackageManager.INSTALL_EXTERNAL;
  10. installFlags &= ~PackageManager.INSTALL_INTERNAL;
  11. } else {
  12. throw new IllegalStateException("Invalid stage location");
  13. }
  14. }
  15. final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
  16. final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
  17. final boolean ephemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
  18. PackageInfoLite pkgLite = null;
  19. if (onInt && onSd) {//如果既有安装在内部的标志,又有安装SD卡上的标志,则设置错误返回
  20. // Check if both bits are set.
  21. Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
  22. ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
  23. } else if (onSd && ephemeral) {//此处与上述类似
  24. Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
  25. ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
  26. } else {
  27. pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
  28. packageAbiOverride);//获取安装包包含有应用信息的PacageInfoLite对象
  29. if (DEBUG_EPHEMERAL && ephemeral) {
  30. Slog.v(TAG, "pkgLite for install: " + pkgLite);
  31. }
  32. /*
  33. * If we have too little free space, try to free cache
  34. * before giving up.
  35. */
  36. //如果安装的位置空间不够,会先尝试清除cache空间
  37. if (!origin.staged && pkgLite.recommendedInstallLocation
  38. == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
  39. // TODO: focus freeing disk space on the target device
  40. final StorageManager storage = StorageManager.from(mContext);
  41. final long lowThreshold = storage.getStorageLowBytes(
  42. Environment.getDataDirectory());
  43. final long sizeBytes = mContainerService.calculateInstalledSize(
  44. origin.resolvedPath, isForwardLocked(), packageAbiOverride);
  45. try {
  46. mInstaller.freeCache(null, sizeBytes + lowThreshold);
  47. pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
  48. installFlags, packageAbiOverride);
  49. } catch (InstallerException e) {
  50. Slog.w(TAG, "Failed to free cache", e);
  51. }
  52. /*
  53. * The cache free must have deleted the file we
  54. * downloaded to install.
  55. *
  56. * TODO: fix the "freeCache" call to not delete
  57. * the file we care about.
  58. */
  59. if (pkgLite.recommendedInstallLocation
  60. == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
  61. pkgLite.recommendedInstallLocation
  62. = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
  63. }
  64. }
  65. }
  66. if (ret == PackageManager.INSTALL_SUCCEEDED) {//如果该标志位依然是INSTALL_SUCCEEDED,则说明前面的校验都通过
  67. int loc = pkgLite.recommendedInstallLocation;
  68. if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
  69. ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
  70. } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
  71. ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
  72. } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
  73. ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  74. } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
  75. ret = PackageManager.INSTALL_FAILED_INVALID_APK;
  76. } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
  77. ret = PackageManager.INSTALL_FAILED_INVALID_URI;
  78. } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
  79. ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
  80. } else {
  81. // Override with defaults if needed.
  82. loc = installLocationPolicy(pkgLite);
  83. if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
  84. ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
  85. } else if (!onSd && !onInt) {
  86. // Override install location with flags
  87. if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
  88. // Set the flag to install on external media.
  89. installFlags |= PackageManager.INSTALL_EXTERNAL;
  90. installFlags &= ~PackageManager.INSTALL_INTERNAL;
  91. } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
  92. if (DEBUG_EPHEMERAL) {
  93. Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
  94. }
  95. installFlags |= PackageManager.INSTALL_EPHEMERAL;
  96. installFlags &= ~(PackageManager.INSTALL_EXTERNAL
  97. |PackageManager.INSTALL_INTERNAL);
  98. } else {
  99. // Make sure the flag for installing on external
  100. // media is unset
  101. installFlags |= PackageManager.INSTALL_INTERNAL;
  102. installFlags &= ~PackageManager.INSTALL_EXTERNAL;
  103. }
  104. }
  105. }
  106. }
  107. final InstallArgs args = createInstallArgs(this);//函数中会有分支处理,这里考虑FileInstallArgs实例创建情况,并会保存一份到InstallParams::mArgs
  108. mArgs = args;
  109. if (ret == PackageManager.INSTALL_SUCCEEDED) {//如果该标志位依然是INSTALL_SUCCEEDED,则说明前面的校验都通过
  110. // TODO: http://b/22976637
  111. // Apps installed for "all" users use the device owner to verify the app
  112. UserHandle verifierUser = getUser();
  113. if (verifierUser == UserHandle.ALL) {
  114. verifierUser = UserHandle.SYSTEM;
  115. }
  116. /*
  117. * Determine if we have any installed package verifiers. If we
  118. * do, then we'll defer to them to verify the packages.
  119. */
  120. final int requiredUid = mRequiredVerifierPackage == null ? -1
  121. : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
  122. verifierUser.getIdentifier());
  123. //if部分是一段执行应用校验的代码,如果需要校验,则通过向系统中所有带有校验功能的组件发送Intent.ACTION_PACKAGE_NEEDS_VERIFICATION广播来完成
  124. if (!origin.existing && requiredUid != -1
  125. && isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) {
  126. final Intent verification = new Intent(
  127. Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
  128. verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
  129. verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
  130. PACKAGE_MIME_TYPE);
  131. verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  132. // Query all live verifiers based on current user state
  133. final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
  134. PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier());
  135. if (DEBUG_VERIFY) {
  136. Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
  137. + verification.toString() + " with " + pkgLite.verifiers.length
  138. + " optional verifiers");
  139. }
  140. final int verificationId = mPendingVerificationToken++;
  141. verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
  142. verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
  143. installerPackageName);
  144. verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
  145. installFlags);
  146. verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
  147. pkgLite.packageName);
  148. verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
  149. pkgLite.versionCode);
  150. if (verificationInfo != null) {
  151. if (verificationInfo.originatingUri != null) {
  152. verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
  153. verificationInfo.originatingUri);
  154. }
  155. if (verificationInfo.referrer != null) {
  156. verification.putExtra(Intent.EXTRA_REFERRER,
  157. verificationInfo.referrer);
  158. }
  159. if (verificationInfo.originatingUid >= 0) {
  160. verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
  161. verificationInfo.originatingUid);
  162. }
  163. if (verificationInfo.installerUid >= 0) {
  164. verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
  165. verificationInfo.installerUid);
  166. }
  167. }
  168. final PackageVerificationState verificationState = new PackageVerificationState(
  169. requiredUid, args);
  170. mPendingVerification.append(verificationId, verificationState);
  171. final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
  172. receivers, verificationState);
  173. /*
  174. * If any sufficient verifiers were listed in the package
  175. * manifest, attempt to ask them.
  176. */
  177. if (sufficientVerifiers != null) {
  178. final int N = sufficientVerifiers.size();
  179. if (N == 0) {
  180. Slog.i(TAG, "Additional verifiers required, but none installed.");
  181. ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
  182. } else {
  183. for (int i = 0; i < N; i++) {
  184. final ComponentName verifierComponent = sufficientVerifiers.get(i);
  185. final Intent sufficientIntent = new Intent(verification);
  186. sufficientIntent.setComponent(verifierComponent);
  187. mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
  188. }
  189. }
  190. }
  191. final ComponentName requiredVerifierComponent = matchComponentForVerifier(
  192. mRequiredVerifierPackage, receivers);
  193. if (ret == PackageManager.INSTALL_SUCCEEDED
  194. && mRequiredVerifierPackage != null) {
  195. Trace.asyncTraceBegin(
  196. TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
  197. /*
  198. * Send the intent to the required verification agent,
  199. * but only start the verification timeout after the
  200. * target BroadcastReceivers have run.
  201. */
  202. verification.setComponent(requiredVerifierComponent);
  203. mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
  204. android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
  205. new BroadcastReceiver() {
  206. @Override
  207. public void onReceive(Context context, Intent intent) {
  208. final Message msg = mHandler
  209. .obtainMessage(CHECK_PENDING_VERIFICATION);
  210. msg.arg1 = verificationId;
  211. mHandler.sendMessageDelayed(msg, getVerificationTimeout());
  212. }
  213. }, null, 0, null, null);
  214. /*
  215. * We don't want the copy to proceed until verification
  216. * succeeds, so null out this field.
  217. */
  218. mArgs = null;
  219. }
  220. } else {//不需要校验,则调用FileInstallArgs::copyApk()继续后续的处理
  221. /*
  222. * No package verification is enabled, so immediately start
  223. * the remote call to initiate copy using temporary file.
  224. */
  225. ret = args.copyApk(mContainerService, true);
  226. }
  227. }
  228. mRet = ret;
  229. }

这里总结下这段代码处理:

  • 首先会进行一些安装标志的判断。
  • 调用 DCS::getMinimalPackageInfo() 方法获取该 APK 安装需要的大小及其他信息,信息会封装到 PackageInfoLite 对象中。
  • 如果检测到当前的目录下的大小不足以安装应用,还回去进行 cache 的清理工作。
  • 随后会以当前的 InstallParams 实例,创建 FileInstallArgs 对象,并保存一份到 InstallParams 对象的 mArgs 字段中。
  • 后续是一段组件校验工作。
  • 最后 FileInstallArgs::copyApk() 函数,进行下一步处理。

接着看 FileInstallArgs::copyApk() 函数:

  1. private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
  2. if (origin.staged) {
  3. if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
  4. codeFile = origin.file;
  5. resourceFile = origin.file;
  6. return PackageManager.INSTALL_SUCCEEDED;
  7. }
  8. try {
  9. final boolean isEphemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
  10. final File tempDir =
  11. mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);//通过PackageInstallService在/data/app/下生成临时文件
  12. codeFile = tempDir;
  13. resourceFile = tempDir;
  14. } catch (IOException e) {
  15. Slog.w(TAG, "Failed to create copy file: " + e);
  16. return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  17. }
  18. //为临时文件目录创建ParcelFileDescriptor描述符,它能在Binder间传递
  19. final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
  20. @Override
  21. public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
  22. if (!FileUtils.isValidExtFilename(name)) {
  23. throw new IllegalArgumentException("Invalid filename: " + name);
  24. }
  25. try {
  26. final File file = new File(codeFile, name);
  27. final FileDescriptor fd = Os.open(file.getAbsolutePath(),
  28. O_RDWR | O_CREAT, 0644);
  29. Os.chmod(file.getAbsolutePath(), 0644);
  30. return new ParcelFileDescriptor(fd);
  31. } catch (ErrnoException e) {
  32. throw new RemoteException("Failed to open: " + e.getMessage());
  33. }
  34. }
  35. };
  36. int ret = PackageManager.INSTALL_SUCCEEDED;
  37. //使用DefaultContainerService::copyPackage()方法执行apk文件的复制
  38. ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
  39. if (ret != PackageManager.INSTALL_SUCCEEDED) {
  40. Slog.e(TAG, "Failed to copy package");
  41. return ret;
  42. }
  43. //安装应用中存在的native动态库,主要是从Apk打包文件中将它们提取出来放置
  44. final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
  45. NativeLibraryHelper.Handle handle = null;
  46. try {
  47. handle = NativeLibraryHelper.Handle.create(codeFile);
  48. ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
  49. abiOverride);
  50. } catch (IOException e) {
  51. Slog.e(TAG, "Copying native libraries failed", e);
  52. ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
  53. } finally {
  54. IoUtils.closeQuietly(handle);
  55. }
  56. return ret;
  57. }

这里的处理有如下几个:

  • 通过 PackageInstallService 为要安装的 APK 在 /data/app/ 下生成一个零时文件 tempDir,它的命名并不以 .apk 结尾。
  • 为该 tempDir 创建 IParcelFileDescriptorFactory 文件描述符,它可以在进程间传递。
  • 调用 DefaultContainerService::copyPackage() 方法执行 APK 临时文件的复制。
  • 最后再将 APK 中包含的一些库文件提取出来,放置到对应的 lib/ 目录下。
  1. @Deprecated
  2. public File allocateStageDirLegacy(String volumeUuid, boolean isEphemeral) throws IOException {
  3. synchronized (mSessions) {
  4. try {
  5. final int sessionId = allocateSessionIdLocked();
  6. mLegacySessions.put(sessionId, true);
  7. final File stageDir = buildStageDir(volumeUuid, sessionId, isEphemeral);
  8. prepareStageDir(stageDir);
  9. return stageDir;
  10. } catch (IllegalStateException e) {
  11. throw new IOException(e);
  12. }
  13. }
  14. }
  15. private File buildStageDir(String volumeUuid, int sessionId, boolean isEphemeral) {
  16. final File stagingDir = buildStagingDir(volumeUuid, isEphemeral);
  17. return new File(stagingDir, "vmdl" + sessionId + ".tmp");
  18. }

临时文件的名称格式大致是:'vmdl-随机数.tmp' 的形式。如果一切过程都正常,至此,APK 安装的第一部分的工作:APK 文件的拷贝,就结束了。根据前面的流程,最后会调用 InstallParams::handleReturnCode() 执行返回结果的处理:

  1. @Override
  2. void handleReturnCode() {
  3. // If mArgs is null, then MCS couldn't be reached. When it
  4. // reconnects, it will try again to install. At that point, this
  5. // will succeed.
  6. if (mArgs != null) {
  7. processPendingInstall(mArgs, mRet);
  8. }
  9. }

因为 InstallParams::mArgs 我们之前赋值过,所以肯定不为空,继续调用 processPendingInstall() 函数:

  1. private void processPendingInstall(final InstallArgs args, final int currentStatus) {
  2. // Queue up an async operation since the package installation may take a little while.
  3. mHandler.post(new Runnable() {
  4. public void run() {
  5. mHandler.removeCallbacks(this);//消息移除,防止此处被重复调用
  6. // Result object to be returned
  7. PackageInstalledInfo res = new PackageInstalledInfo();
  8. res.setReturnCode(currentStatus);
  9. res.uid = -1;
  10. res.pkg = null;
  11. res.removedInfo = null;
  12. if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {//如果之前的处理顺利完成
  13. args.doPreInstall(res.returnCode);
  14. synchronized (mInstallLock) {
  15. installPackageTracedLI(args, res);//则需要去解析、装载应用
  16. }
  17. args.doPostInstall(res.returnCode, res.uid);
  18. }
  19. // A restore should be performed at this point if (a) the install
  20. // succeeded, (b) the operation is not an update, and (c) the new
  21. // package has not opted out of backup participation.
  22. //后面一段都在执行备份操作
  23. final boolean update = res.removedInfo != null
  24. && res.removedInfo.removedPackage != null;
  25. final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
  26. boolean doRestore = !update
  27. && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
  28. // Set up the post-install work request bookkeeping. This will be used
  29. // and cleaned up by the post-install event handling regardless of whether
  30. // there's a restore pass performed. Token values are >= 1.
  31. int token;
  32. if (mNextInstallToken < 0) mNextInstallToken = 1;
  33. token = mNextInstallToken++;
  34. PostInstallData data = new PostInstallData(args, res);
  35. mRunningInstalls.put(token, data);
  36. if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
  37. if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
  38. // Pass responsibility to the Backup Manager. It will perform a
  39. // restore if appropriate, then pass responsibility back to the
  40. // Package Manager to run the post-install observer callbacks
  41. // and broadcasts.
  42. IBackupManager bm = IBackupManager.Stub.asInterface(
  43. ServiceManager.getService(Context.BACKUP_SERVICE));
  44. if (bm != null) {
  45. if (DEBUG_INSTALL) Log.v(TAG, "token " + token
  46. + " to BM for possible restore");
  47. Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
  48. try {
  49. // TODO: http://b/22388012
  50. if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
  51. bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
  52. } else {
  53. doRestore = false;
  54. }
  55. } catch (RemoteException e) {
  56. // can't happen; the backup manager is local
  57. } catch (Exception e) {
  58. Slog.e(TAG, "Exception trying to enqueue restore", e);
  59. doRestore = false;
  60. }
  61. } else {
  62. Slog.e(TAG, "Backup Manager not found!");
  63. doRestore = false;
  64. }
  65. }
  66. if (!doRestore) {//直接去处理安装请求
  67. // No restore possible, or the Backup Manager was mysteriously not
  68. // available -- just fire the post-install work request directly.
  69. if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
  70. Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
  71. Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);//此处发送POST_INSTALL消息,继续处理流程
  72. mHandler.sendMessage(msg);
  73. }
  74. }
  75. });
  76. }

函数内会调用 FileInstallArgs 的 doPreInstall()/doPostInstall() 函数进行一些清理工作。其中 PMS::installPackageTracedLI() 函数的主要功能就是将当前安装的 APK 加入到它的管理体系中,以便之后统一管理;特殊的,该函数内部会调用 FileInstallArgs::doReanme() 函数将之前的 APK 备份文件重命名。具体的实现是扫描 APK 的过程,这部分之前已经有介绍过。

略去之后的备份工作后,最后会发送 POST_INSTALL 消息,依旧是 PackageHandler 处理:

  1. case POST_INSTALL: {//应用安装的收尾处理:主要动作是发送广播,通知系统中其他应用,开始某些处理工作:如果Launcher添加应用图标等
  2. if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
  3. PostInstallData data = mRunningInstalls.get(msg.arg1);
  4. final boolean didRestore = (msg.arg2 != 0);
  5. mRunningInstalls.delete(msg.arg1);
  6. if (data != null) {
  7. InstallArgs args = data.args;
  8. PackageInstalledInfo parentRes = data.res;
  9. final boolean grantPermissions = (args.installFlags
  10. & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
  11. final boolean killApp = (args.installFlags
  12. & PackageManager.INSTALL_DONT_KILL_APP) == 0;
  13. final String[] grantedPermissions = args.installGrantPermissions;
  14. // Handle the parent package
  15. handlePackagePostInstall(parentRes, grantPermissions, killApp,
  16. grantedPermissions, didRestore, args.installerPackageName,
  17. args.observer);//各种广播的发送处理
  18. // Handle the child packages
  19. final int childCount = (parentRes.addedChildPackages != null)
  20. ? parentRes.addedChildPackages.size() : 0;
  21. for (int i = 0; i < childCount; i++) {
  22. PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
  23. handlePackagePostInstall(childRes, grantPermissions, killApp,
  24. grantedPermissions, false, args.installerPackageName,
  25. args.observer);
  26. }
  27. // Log tracing if needed
  28. if (args.traceMethod != null) {
  29. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
  30. args.traceCookie);
  31. }
  32. } else {
  33. Slog.e(TAG, "Bogus post-install token " + msg.arg1);
  34. }
  35. Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1);
  36. } break;

由于需要安装的 APK 文件已经拷贝到了系统中,并且 PKMS 也已经对它进行了统一管理,到此 APK 的安装工作就基本完成了。
但是,此时系统其它组件并不知道此时有新的 APK 安装进了系统中,所以这里需要发送一些广播给感兴趣的接收者,通知它们当前有新的 APK 安装完成了。这一部分最明显的就是 Launcher 了,我们安装 APK 后,Launcher 上要添加图标,就是根据这部分内容来的。发送广播的主要函数是 handlePackagePostInstall(),它的实现如下:

    1. private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
    2. boolean killApp, String[] grantedPermissions,
    3. boolean launchedForRestore, String installerPackage,
    4. IPackageInstallObserver2 installObserver) {
    5. if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
    6. // Send the removed broadcasts
    7. if (res.removedInfo != null) {
    8. res.removedInfo.sendPackageRemovedBroadcasts(killApp);
    9. }
    10. // Now that we successfully installed the package, grant runtime
    11. // permissions if requested before broadcasting the install.
    12. if (grantPermissions && res.pkg.applicationInfo.targetSdkVersion
    13. >= Build.VERSION_CODES.M) {
    14. grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions);
    15. }
    16. final boolean update = res.removedInfo != null
    17. && res.removedInfo.removedPackage != null;
    18. // If this is the first time we have child packages for a disabled privileged
    19. // app that had no children, we grant requested runtime permissions to the new
    20. // children if the parent on the system image had them already granted.
    21. if (res.pkg.parentPackage != null) {
    22. synchronized (mPackages) {
    23. grantRuntimePermissionsGrantedToDisabledPrivSysPackageParentLPw(res.pkg);
    24. }
    25. }
    26. synchronized (mPackages) {
    27. mEphemeralApplicationRegistry.onPackageInstalledLPw(res.pkg);
    28. }
    29. final String packageName = res.pkg.applicationInfo.packageName;
    30. Bundle extras = new Bundle(1);
    31. extras.putInt(Intent.EXTRA_UID, res.uid);
    32. int[] firstUsers = EMPTY_INT_ARRAY;
    33. int[] updateUsers = EMPTY_INT_ARRAY;
    34. if (res.origUsers == null || res.origUsers.length == 0) {
    35. firstUsers = res.newUsers;
    36. } else {
    37. for (int newUser : res.newUsers) {
    38. boolean isNew = true;
    39. for (int origUser : res.origUsers) {
    40. if (origUser == newUser) {
    41. isNew = false;
    42. break;
    43. }
    44. }
    45. if (isNew) {
    46. firstUsers = ArrayUtils.appendInt(firstUsers, newUser);
    47. } else {
    48. updateUsers = ArrayUtils.appendInt(updateUsers, newUser);
    49. }
    50. }
    51. }
    52. // Send installed broadcasts if the install/update is not ephemeral
    53. if (!isEphemeral(res.pkg)) {
    54. mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);
    55. // Send added for users that see the package for the first time
    56. sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
    57. extras, 0 /*flags*/, null /*targetPackage*/,
    58. null /*finishedReceiver*/, firstUsers);//首先要发送Intent.ACTION_PACKAGE_ADDED广播,表明系统中有新的apk被安装了
    59. // Send added for users that don't see the package for the first time
    60. if (update) {
    61. extras.putBoolean(Intent.EXTRA_REPLACING, true);
    62. }
    63. sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
    64. extras, 0 /*flags*/, null /*targetPackage*/,
    65. null /*finishedReceiver*/, updateUsers);
    66. // Send replaced for users that don't see the package for the first time
    67. if (update) {//如果当前安装是升级,则还需要发送更多的广播:Intent.ACTION_PACKAGE_REPLACED/Intent.ACTION_MY_PACKAGE_REPLACED
    68. sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
    69. packageName, extras, 0 /*flags*/,
    70. null /*targetPackage*/, null /*finishedReceiver*/,
    71. updateUsers);
    72. sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
    73. null /*package*/, null /*extras*/, 0 /*flags*/,
    74. packageName /*targetPackage*/,
    75. null /*finishedReceiver*/, updateUsers);
    76. } else if (launchedForRestore && !isSystemApp(res.pkg)) {
    77. // First-install and we did a restore, so we're responsible for the
    78. // first-launch broadcast.
    79. if (DEBUG_BACKUP) {
    80. Slog.i(TAG, "Post-restore of " + packageName
    81. + " sending FIRST_LAUNCH in " + Arrays.toString(firstUsers));
    82. }
    83. sendFirstLaunchBroadcast(packageName, installerPackage, firstUsers);
    84. }
    85. // Send broadcast package appeared if forward locked/external for all users
    86. // treat asec-hosted packages like removable media on upgrade
    87. if (res.pkg.isForwardLocked() || isExternal(res.pkg)) {//如果安装的是foreword lock应用或是安装在SD卡上的应用,也有相关的广播要发送
    88. if (DEBUG_INSTALL) {
    89. Slog.i(TAG, "upgrading pkg " + res.pkg
    90. + " is ASEC-hosted -> AVAILABLE");
    91. }
    92. final int[] uidArray = new int[]{res.pkg.applicationInfo.uid};
    93. ArrayList<String> pkgList = new ArrayList<>(1);
    94. pkgList.add(packageName);
    95. sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null);
    96. }
    97. }
    98. // Work that needs to happen on first install within each user
    99. if (firstUsers != null && firstUsers.length > 0) {
    100. synchronized (mPackages) {
    101. for (int userId : firstUsers) {
    102. if (packageIsBrowser(packageName, userId)) {
    103. mSettings.setDefaultBrowserPackageNameLPw(null, userId);
    104. }
    105. mSettings.applyPendingPermissionGrantsLPw(packageName, userId);
    106. }
    107. }
    108. }
    109. EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
    110. getUnknownSourcesSettings());
    111. Runtime.getRuntime().gc();
    112. if (res.removedInfo != null && res.removedInfo.args != null) {
    113. synchronized (mInstallLock) {
    114. res.removedInfo.args.doPostDeleteLI(true);
    115. }
    116. }
    117. }
    118. if (installObserver != null) {//回调接口调用,反馈最终安装的结果
    119. try {
    120. Bundle extras = extrasForInstallResult(res);
    121. installObserver.onPackageInstalled(res.name, res.returnCode,
    122. res.returnMsg, extras);
    123. } catch (RemoteException e) {
    124. Slog.i(TAG, "Observer no longer exists.");
    125. }
    126. }
    127. }

主要处理就是发送各种广播,比如:

  • Intent.ACTION_PACKAGE_ADDED:通知系统其它组件,当前有新的apk安装成功了。
  • Launcher;Launcher 再去向 PKMS 查询所有带有主 Activity 的应用信息,更新显示。最后再通过用户注册的 Observer 回调对象将安装结果回调给监听者。

分析到这里,一个 APK 的安装过程就简要地分析完成了。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/199144
推荐阅读
相关标签
  

闽ICP备14008679号