[toc]
基于 Android 7.1.1 源码分析 PackageManagerService 的架构和逻辑实现!
0 综述 本篇文章总结下 install package 的过程,在 Abdroid 7.1.1 上安装一个应用有如下的方式:
adb install(根据情况转为 cmd package install 或者 pm install)
adb shell cmd package install(目前都是优先使用)
adb shell pm install;
拷贝 apk 到文件管理器中触发安装;
通过应用商店安装;
这里我们先从 adb install 入手,对于其他的安装方式,我们后面再分析!
1 adb install - commandline::adb_commandline adb install 的执行从 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 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 int adb_commandline (int argc, const char **argv) { ... ... ... else if (!strcmp (argv[0 ], "push" )) { bool copy_attrs = false ; std ::vector <const char *> srcs; const char * dst = nullptr ; parse_push_pull_args(&argv[1 ], argc - 1 , &srcs, &dst, ©_attrs); if (srcs.empty() || !dst) return usage(); return do_sync_push(srcs, dst) ? 0 : 1 ; } ... ... ... else if (!strcmp (argv[0 ], "install" )) { if (argc < 2 ) return usage(); if (_use_legacy_install()) { return install_app_legacy(transport_type, serial, argc, argv); } return install_app(transport_type, serial, argc, argv); } else if (!strcmp (argv[0 ], "install-multiple" )) { if (argc < 2 ) return usage(); return install_multiple_app(transport_type, serial, argc, 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 命令的情况下,会调用 install_app;
如果不支持,执行 install_app_legacy 方法!
1.1 cmd install - 支持 cmd 指令 1.1.1 commandline::install_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 static int install_app (TransportType transport, const char * serial, int argc, const char ** argv) { const char * file = argv[argc - 1 ]; const char * dot = strrchr(file, '.' ); bool found_apk = false ; struct stat sb; if (dot && !strcasecmp(dot, ".apk" )) { if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) { fprintf(stderr, "Invalid APK file: %s\n" , file); return EXIT_FAILURE; } found_apk = true ; } if (!found_apk) { fprintf(stderr, "Missing APK file\n" ); return EXIT_FAILURE; } int localFd = adb_open(file, O_RDONLY); if (localFd < 0 ) { fprintf(stderr, "Failed to open %s: %s\n" , file, strerror(errno)); return 1 ; } std::string error; std::string cmd = "exec:cmd package" ; while (argc-- > 1 ) { cmd += " " + escape_arg(std::string(*argv++)); } cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size)); int remoteFd = adb_connect(cmd, &error); if (remoteFd < 0 ) { fprintf(stderr, "Connect error for write: %s\n" , error.c_str()); adb_close(localFd); return 1 ; } char buf[BUFSIZ]; copy_to_file(localFd, remoteFd); read_status_line(remoteFd, buf, sizeof(buf)); adb_close(localFd); adb_close(remoteFd); if (strncmp("Success" , buf, 7 )) { fprintf(stderr, "Failed to install %s: %s" , file, buf); return 1 ; } fputs(buf, stderr); return 0 ; }
1.1.5 new PackageManagerShellCommand 1.1.5.1 onCommand 最终,会调用 PackageManagerShellCommand 的 onCommand 方法:
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 class PackageManagerShellCommand extends ShellCommand { ... ... ... ... @Override public int onCommand (String cmd) { if (cmd == null ) { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); try { switch (cmd) { case "install" : return runInstall(); case "install-abandon" : case "install-destroy" : return runInstallAbandon(); case "install-commit" : return runInstallCommit(); case "install-create" : return runInstallCreate(); case "install-remove" : return runInstallRemove(); case "install-write" : return runInstallWrite(); ... ... ... default : return handleDefaultCommands(cmd); } } catch (RemoteException e) { pw.println("Remote exception: " + e); } return -1 ; } }
这里我们先看 runInstall,其他指令相对于 runInstall 简单了不少!
1.1.5.2 runInstall 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 private int runInstall () throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final InstallParams params = makeInstallParams(); final String inPath = getNextArg(); boolean installExternal = (params.sessionParams.installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ; if (params.sessionParams.sizeBytes < 0 && inPath != null ) { File file = new File(inPath); if (file.isFile()) { if (installExternal) { try { ApkLite baseApk = PackageParser.parseApkLite(file, 0 ); PackageLite pkgLite = new PackageLite(null , baseApk, null , null , null ); params.sessionParams.setSize( PackageHelper.calculateInstalledSize(pkgLite, false , params.sessionParams.abiOverride)); } catch (PackageParserException | IOException e) { pw.println("Error: Failed to parse APK file : " + e); return 1 ; } } else { params.sessionParams.setSize(file.length()); } } } final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true ; try { if (inPath == null && params.sessionParams.sizeBytes == 0 ) { pw.println("Error: must either specify a package size or an APK file" ); return 1 ; } if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk" , 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) { } } } }
1.1.5.2.1 makeInstallParams 这个和 pm install 的流程是一样的,虽然这个同名方法是在 PackageManagerShellCommand 中,但实际上两个方法的代码一模一样,大家可以参考【*2.9.1】!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private InstallParams makeInstallParams () { final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); final InstallParams params = new InstallParams(); params.sessionParams = sessionParams; String opt; while ((opt = getNextOption()) != null ) { switch (opt) { case "-l" : sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; break ; case "-r" : sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; break ; ... ... ... default : throw new IllegalArgumentException("Unknown option " + opt); } } return params; }
不多说了!
1.1.5.2.2 doCreateSession 这个和 pm install 的流程是一样的,虽然这个同名方法是在 PackageManagerShellCommand 中,但实际上两个方法的代码几乎一模一样,大家可以参考【*2.9.2】!
1 2 3 4 5 6 7 8 9 10 11 12 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; }
这里的 mInterface 是 PMS 的代理对象,通过 getPackageInstaller 获得了 PackageInstallerService 实例!
1.1.5.2.3 doWriteSplit doWriteSplit 方法和 2.9.3 Pm.doWriteSession 是一样的:
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 private int doWriteSplit (int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); if (sizeBytes <= 0 ) { pw.println("Error: must specify a APK size" ); return 1 ; } if (inPath != null && !"-" .equals(inPath)) { pw.println("Error: APK content must be streamed" ); return 1 ; } inPath = null ; final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId); PackageInstaller.Session session = null ; InputStream in = null ; OutputStream out = null ; try { session = new PackageInstaller.Session( mInterface.getPackageInstaller().openSession(sessionId)); if (inPath != null ) { in = new FileInputStream(inPath); } else { in = new SizedInputStream(getRawInputStream(), sizeBytes); } out = session.openWrite(splitName, 0 , sizeBytes); int total = 0 ; byte [] buffer = new byte [65536 ]; int c; while ((c = in.read(buffer)) != -1 ) { total += c; out.write(buffer, 0 , c); if (info.sizeBytes > 0 ) { final float fraction = ((float ) c / (float ) info.sizeBytes); session.addProgress(fraction); } } session.fsync(out); if (logSuccess) { pw.println("Success: streamed " + total + " bytes" ); } return 0 ; } catch (IOException e) { pw.println("Error: failed to write; " + e.getMessage()); return 1 ; } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); IoUtils.closeQuietly(session); } }
不多说了!
1.1.5.2.4 doCommitSession doWriteSplit 方法和 2.9.4 Pm.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 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); } }
1.2 pm install - 不支持 cmd 指令 1.2.1 commandline::install_app_legacy 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 static int install_app_legacy (TransportType transport, const char * serial, int argc, const char ** argv) { static const char *const DATA_DEST = "/data/local/tmp/%s" ; static const char *const SD_DEST = "/sdcard/tmp/%s" ; const char * where = DATA_DEST; int i; struct stat sb ; for (i = 1 ; i < argc; i++) { if (!strcmp (argv[i], "-s" )) { where = SD_DEST; } } int last_apk = -1 ; for (i = argc - 1 ; i >= 0 ; i--) { const char * file = argv[i]; const char * dot = strrchr (file, '.' ); if (dot && !strcasecmp(dot, ".apk" )) { if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) { fprintf (stderr , "Invalid APK file: %s\n" , file); return EXIT_FAILURE; } last_apk = i; break ; } } if (last_apk == -1 ) { fprintf (stderr , "Missing APK file\n" ); return EXIT_FAILURE; } int result = -1 ; std ::vector <const char *> apk_file = {argv[last_apk]}; std ::string apk_dest = android::base::StringPrintf( where, adb_basename(argv[last_apk]).c_str());、 if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk; argv[last_apk] = apk_dest.c_str(); result = pm_command(transport, serial, argc, argv); cleanup_apk: delete_file(transport, serial, apk_dest); return result; }
其实整个过程很简单,不多说了!
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 41 42 43 44 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 服务发送 pm 命令,触发 apk 的安装!
2 pm install cmd 的调用上面已经分析了,其实和 pm install 没有区别!
这里我们来看下 pm 命令的主要用法,通过 pm 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 25 26 27 28 29 30 31 32 33 34 usage: pm path [--user USER_ID] PACKAGE pm dump PACKAGE pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH] pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES] [--install-location 0 /1 /2 ] [--force-uuid internal|UUID] pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH] pm install-commit SESSION_ID pm install-abandon SESSION_ID pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE pm set-installer PACKAGE INSTALLER pm move-package PACKAGE [internal|UUID] pm move-primary-storage [internal|UUID] pm clear [--user USER_ID] PACKAGE pm enable [--user USER_ID] PACKAGE_OR_COMPONENT pm disable [--user USER_ID] PACKAGE_OR_COMPONENT pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT pm default -state [--user USER_ID] PACKAGE_OR_COMPONENT pm set-user-restriction [--user USER_ID] RESTRICTION VALUE pm hide [--user USER_ID] PACKAGE_OR_COMPONENT pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT pm grant [--user USER_ID] PACKAGE PERMISSION pm revoke [--user USER_ID] PACKAGE PERMISSION pm reset-permissions pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined} pm get-app-link [--user USER_ID] PACKAGE pm set-install-location [0 /auto] [1 /internal] [2 /external] pm get-install-location pm set-permission-enforced PERMISSION [true |false ] pm trim-caches DESIRED_FREE_SPACE [internal|UUID] pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME pm remove-user USER_ID pm get-max-users
pm 命令的源码位于 frameworks/base/cmds/pm 中,我们直接去看下目录结构:
1 2 3 4 5 6 7 8 9 10 11 . ├── Android.mk ├── MODULE_LICENSE_APACHE2 ├── NOTICE ├── pm └── src └── com └── android └── commands └── pm └── Pm.java
我们先来看看 Android.mk 中的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # Copyright 2007 The Android Open Source Project # LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := pm include $(BUILD_JAVA_LIBRARY) include $(CLEAR_VARS) ALL_PREBUILT += $(TARGET_OUT)/bin/pm $(TARGET_OUT)/bin/pm : $(LOCAL_PATH)/pm | $(ACP) $(transform-prebuilt-to-target)
可以看到,编译期间,编译系统会将 pm 脚本放置到 /system/bin/ 目录下。
接着,来看看 pm 脚本的内容:1 2 3 4 5 6 # Script to start "pm" on the device, which has a very rudimentary # shell. # base=/system export CLASSPATH=$base/framework/pm.jar exec app_process $base/bin com.android.commands.pm.Pm "$@"
该脚本的作用是通过 app_process 启动 pm java 进程!
2.1 app_process::main app_process 其实就是 Zygote 的源码,在开机篇我们已经分析过了 Zygote 的启动,这里略过和 Zygote 相关的代码:
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 int main (int argc, char * const argv[]) { ... ... ... ++i; while (i < argc) { const char * arg = argv[i++]; if (strcmp (arg, "--zygote" ) == 0 ) { zygote = true ; niceName = ZYGOTE_NICE_NAME; } else if (strcmp (arg, "--start-system-server" ) == 0 ) { startSystemServer = true ; } else if (strcmp (arg, "--application" ) == 0 ) { application = true ; } else if (strncmp (arg, "--nice-name=" , 12 ) == 0 ) { niceName.setTo(arg + 12 ); } else if (strncmp (arg, "--" , 2 ) != 0 ) { className.setTo(arg); break ; } else { --i; break ; } } Vector<String8> args; if (!className.isEmpty()) { args.add(application ? String8("application" ) : String8("tool" )); runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { ... ... ... } if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string ()); set_process_name(niceName.string ()); } if (zygote) { runtime.start("com.android.internal.os.ZygoteInit" , args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit" , args, zygote); } else { fprintf (stderr , "Error: no class name or --zygote supplied.\n" ); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied." ); return 10 ; } }
接下来,会进入 AndroidRuntime 中去!!
2.2 AndroidRuntime::start 这里的 className 传入的值为 com.android.internal.os.RuntimeInit!
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 void AndroidRuntime::start(const char * className, const Vector<String8>& options, bool zygote){ ALOGD(">>>>>> START %s uid %d <<<<<<\n" , className != NULL ? className : "(unknown)" , getuid()); static const String8 startSystemServer ("start-system-server" ) ; for (size_t i = 0 ; i < options.size(); ++i) { if (options[i] == startSystemServer) { const int LOG_BOOT_PROGRESS_START = 3000 ; LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); } } const char * rootDir = getenv("ANDROID_ROOT" ); if (rootDir == NULL) { rootDir = "/system" ; if (!hasDir("/system" )) { LOG_FATAL("No root directory specified, and /android does not exist." ); return ; } setenv("ANDROID_ROOT" , rootDir, 1 ); } JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0 ) { return ; } onVmCreated(env); if (startReg(env) < 0 ) { ALOGE("Unable to register all android natives\n" ); return ; } jclass stringClass; jobjectArray strArray; jstring classNameStr; stringClass = env->FindClass("java/lang/String" ); assert (stringClass != NULL); strArray = env->NewObjectArray(options.size() + 1 , stringClass, NULL); assert (strArray != NULL); classNameStr = env->NewStringUTF(className); assert (classNameStr != NULL); env->SetObjectArrayElement(strArray, 0 , classNameStr); for (size_t i = 0 ; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert (optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1 , optionsStr); } char * slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n" , slashClassName); } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main" , "([Ljava/lang/String;)V" ); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n" , className); } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName); ALOGD("Shutting down VM\n" ); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n" ); if (mJavaVM->DestroyJavaVM() != 0 ) ALOGW("Warning: VM did not shut down cleanly\n" ); }
通过反射,进入 RuntimeInit 中!
2.3 RuntimeInit.main 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static final void main (String[] argv) { enableDdms(); if (argv.length == 2 && argv[1 ].equals("application" )) { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application" ); redirectLogStreams(); } else { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool" ); } commonInit(); nativeFinishInit(); if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!" ); }
nativeFinishInit 调用的是 native 方法,位于 AndroidRuntime.cpp 文件中!
1 2 3 4 5 static void com_android_internal_os_RuntimeInit_nativeFinishInit (JNIEnv* env, jobject clazz) { gCurRuntime->onStarted(); }
实际上 AndroidRuntime 并没有实现 onStarted 方法,真正是实现是在 App_main.cpp 中的 AppRuntime 类中,他是 AndroidRuntime 的子类!
2.5 AppRuntime::onStarted 1 2 3 4 5 6 7 8 9 10 11 virtual void onStarted () { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n" ); proc->startThreadPool(); AndroidRuntime* ar = AndroidRuntime::getRuntime(); ar->callMain(mClassName, mClass, mArgs); IPCThreadState::self()->stopProcess(); }
2.6 AndroidRuntime::callMain 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 status_t AndroidRuntime::callMain(const String8& className, jclass clazz, const Vector<String8>& args) { JNIEnv* env; jmethodID methodId; ALOGD("Calling main entry %s" , className.string()); env = getJNIEnv(); if (clazz == NULL || env == NULL) { return UNKNOWN_ERROR; } methodId = env->GetStaticMethodID(clazz, "main" , "([Ljava/lang/String;)V" ); if (methodId == NULL) { ALOGE("ERROR: could not find method %s.main(String[])\n" , className.string()); return UNKNOWN_ERROR; } jclass stringClass; jobjectArray strArray; const size_t numArgs = args.size(); stringClass = env->FindClass("java/lang/String" ); strArray = env->NewObjectArray(numArgs, stringClass, NULL); for (size_t i = 0 ; i < numArgs; i++) { jstring argStr = env->NewStringUTF(args[i].string()); env->SetObjectArrayElement(strArray, i, argStr); } env->CallStaticVoidMethod(clazz, methodId, strArray); return NO_ERROR; }
2.7 Pm.main 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void main (String[] args) { int exitCode = 1 ; try { exitCode = new Pm().run(args); } catch (Exception e) { Log.e(TAG, "Error" , e); System.err.println("Error: " + e); if (e instanceof RemoteException) { System.err.println(PM_NOT_RUNNING_ERR); } } System.exit(exitCode); }
2.8 Pm.run run 方法中涉及到的命令有很多,这里我们重点关注和 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 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 public int run (String[] args) throws RemoteException { boolean validCommand = false ; if (args.length < 1 ) { return showUsage(); } mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE)); mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE)); mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package" )); if (mPm == null ) { System.err.println(PM_NOT_RUNNING_ERR); return 1 ; } mInstaller = mPm.getPackageInstaller(); mArgs = args; String op = args[0 ]; mNextArg = 1 ; ... ... ... if ("install" .equals(op)) { return runInstall(); } ... ... ... ... try { if (args.length == 1 ) { if (args[0 ].equalsIgnoreCase("-l" )) { validCommand = true ; return runShellCommand("package" , new String[] { "list" , "package" }); } else if (args[0 ].equalsIgnoreCase("-lf" )) { validCommand = true ; return runShellCommand("package" , new String[] { "list" , "package" , "-f" }); } } else if (args.length == 2 ) { if (args[0 ].equalsIgnoreCase("-p" )) { validCommand = true ; return displayPackageFilePath(args[1 ], UserHandle.USER_SYSTEM); } } return 1 ; } finally { if (validCommand == false ) { if (op != null ) { System.err.println("Error: unknown command '" + op + "'" ); } showUsage(); } } }
继续看!
2.9 Pm.runInstall 我们继续分析:
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 private int runInstall () throws RemoteException { final InstallParams params = makeInstallParams(); final String inPath = nextArg(); boolean installExternal = (params.sessionParams.installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ; if (params.sessionParams.sizeBytes < 0 && inPath != null ) { File file = new File(inPath); if (file.isFile()) { if (installExternal) { try { ApkLite baseApk = PackageParser.parseApkLite(file, 0 ); PackageLite pkgLite = new PackageLite(null , baseApk, null , null , null ); params.sessionParams.setSize( PackageHelper.calculateInstalledSize(pkgLite, false , params.sessionParams.abiOverride)); } catch (PackageParserException | IOException e) { System.err.println("Error: Failed to parse APK file : " + e); return 1 ; } } else { params.sessionParams.setSize(file.length()); } } } final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); try { if (inPath == null && params.sessionParams.sizeBytes == 0 ) { System.err.println("Error: must either specify a package size or an APK file" ); return 1 ; } if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk" , false ) != PackageInstaller.STATUS_SUCCESS) { return 1 ; } if (doCommitSession(sessionId, false ) != PackageInstaller.STATUS_SUCCESS) { return 1 ; } System.out.println("Success" ); return 0 ; } finally { try { mInstaller.abandonSession(sessionId); } catch (Exception ignore) { } } }
2.9.1 Pm.makeInstallParams - 创建事务参数 Pm 中会根据传入的安装参数,创建 InstallParams,封装安装参数!
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 private InstallParams makeInstallParams () { final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); final InstallParams params = new InstallParams(); params.sessionParams = sessionParams; String opt; while ((opt = nextOption()) != null ) { switch (opt) { case "-l" : sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; break ; case "-r" : sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; break ; case "-i" : params.installerPackageName = nextArg(); if (params.installerPackageName == null ) { throw new IllegalArgumentException("Missing installer package" ); } break ; case "-t" : sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST; break ; case "-s" : sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL; break ; case "-f" : sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL; break ; case "-d" : sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; break ; case "-g" : sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; break ; case "--dont-kill" : sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP; break ; case "--originating-uri" : sessionParams.originatingUri = Uri.parse(nextOptionData()); break ; case "--referrer" : sessionParams.referrerUri = Uri.parse(nextOptionData()); break ; case "-p" : sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING; sessionParams.appPackageName = nextOptionData(); if (sessionParams.appPackageName == null ) { throw new IllegalArgumentException("Missing inherit package name" ); } break ; case "-S" : sessionParams.setSize(Long.parseLong(nextOptionData())); break ; case "--abi" : sessionParams.abiOverride = checkAbiArgument(nextOptionData()); break ; case "--ephemeral" : sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL; break ; case "--user" : params.userId = UserHandle.parseUserArg(nextOptionData()); break ; case "--install-location" : sessionParams.installLocation = Integer.parseInt(nextOptionData()); break ; case "--force-uuid" : sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID; sessionParams.volumeUuid = nextOptionData(); if ("internal" .equals(sessionParams.volumeUuid)) { sessionParams.volumeUuid = null ; } break ; case "--force-sdk" : sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK; break ; default : throw new IllegalArgumentException("Unknown option " + opt); } } return params; }
额外的参数很多,根据额外的参数,对 SessionParams 进行了属性设置!
sessionParams.installFlags 会根据不同的额外参数,设置不同的二进制位,具体的含义我上面也简单的注释了下。大家可以自己去看源码!
这里我们要注意下:
如果我们安装的是 split apk 的话,那么我们可以指定 -p 参数,后面指定主 apk 的包名,后面我们会分析其作用!
2.9.1.1 new SessionParams SessionParams 定义在 PackageInstaller.java 文件中:
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 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; } public SessionParams (Parcel source) { mode = source.readInt(); installFlags = source.readInt(); installLocation = source.readInt(); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null ); appLabel = source.readString(); originatingUri = source.readParcelable(null ); originatingUid = source.readInt(); referrerUri = source.readParcelable(null ); abiOverride = source.readString(); volumeUuid = source.readString(); grantedRuntimePermissions = source.readStringArray(); } ... ... ... ... }
这里我们来说下 mode 属性,它可以取三个值:
1 2 3 4 5 6 7 8 public static final int MODE_INVALID = -1 ;public static final int MODE_FULL_INSTALL = 1 ;public static final int MODE_INHERIT_EXISTING = 2 ;
我们省略掉暂时用不到的一些接口,后面有机会再分析!
2.9.1.2 new Pm.InstallParams InstallParams 类很简单,内部有一个 SessionParams 实例变量,封装安装参数!1 2 3 4 5 private static class InstallParams { SessionParams sessionParams; String installerPackageName; int userId = UserHandle.USER_ALL; }
2.9.2 Pm.doCreateSession - 创建事务 创建 install Session 对象!
1 2 3 4 5 6 7 8 9 10 11 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 = mInstaller.createSession(params, installerPackageName, userId); return sessionId; }
进入了 PackageInstallerService 服务,创建 Session 对象!
2.9.3 Pm.doWriteSession - 写入事务(实际上是拷贝文件) 回顾下参数:
1 2 if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk" ,...))
这里的 splitName 值为 “base.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 private int doWriteSession (int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess) throws RemoteException { if ("-" .equals(inPath)) { inPath = null ; } else if (inPath != null ) { final File file = new File(inPath); if (file.isFile()) { sizeBytes = file.length(); } } final SessionInfo info = mInstaller.getSessionInfo(sessionId); PackageInstaller.Session session = null ; InputStream in = null ; OutputStream out = null ; try { session = new PackageInstaller.Session( mInstaller.openSession(sessionId)); if (inPath != null ) { in = new FileInputStream(inPath); } else { in = new SizedInputStream(System.in, sizeBytes); } out = session.openWrite(splitName, 0 , sizeBytes); int total = 0 ; byte [] buffer = new byte [65536 ]; int c; while ((c = in.read(buffer)) != -1 ) { total += c; out.write(buffer, 0 , c); if (info.sizeBytes > 0 ) { final float fraction = ((float ) c / (float ) info.sizeBytes); session.addProgress(fraction); } } session.fsync(out); if (logSuccess) { System.out.println("Success: streamed " + total + " bytes" ); } return PackageInstaller.STATUS_SUCCESS; } catch (IOException e) { System.err.println("Error: failed to write; " + e.getMessage()); return PackageInstaller.STATUS_FAILURE; } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); IoUtils.closeQuietly(session); } }
doWriteSession 整个流程其实就是进行 apk 的拷贝操作!
2.9.3.1 new PackageInstaller.Session Session 是对 PackageInstallerSession 的简单封装!
1 2 3 4 5 6 7 public static class Session implements Closeable { private IPackageInstallerSession mSession; public Session (IPackageInstallerSession session) { mSession = session; }
mSession 指向了对应的 PackageInstallerSession 实例!
同时其还提供了很多借口,来操作 PackageInstallerSession,这里我们用一张图先简单的看下:
1 2 3 4 5 6 7 8 9 10 Session.setProgress -> PackageInstallerSession.setClientProgress Session.setStagingProgress -> PackageInstallerSession.setClientProgress Session.addProgress -> PackageInstallerSession.addClientProgress Session.openWrite -> PackageInstallerSession.openWrite Session.openRead -> PackageInstallerSession.openRead Session.commit -> PackageInstallerSession.commit Session.abandon -> PackageInstallerSession.abandon ... ... ...
这里我们先来看目前已经涉及到的一些重要方法:
2.9.3.1.1 Session.openWrite 这里的 name 传入的是 base.apk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public @NonNull OutputStream openWrite (@NonNull String name, long offsetBytes, long lengthBytes) throws IOException { try { final ParcelFileDescriptor clientSocket = mSession.openWrite(name, offsetBytes, lengthBytes); return new FileBridge.FileBridgeOutputStream(clientSocket); } catch (RuntimeException e) { ExceptionUtils.maybeUnwrapIOException(e); throw e; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
mSession.openWrite 方法涉及到了文件相关处理,这里就不过多关注!
2.9.3.1.2 Session.addProgress 1 2 3 4 5 6 7 8 9 public void addProgress (float progress) { try { mSession.addClientProgress(progress); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
继续来看:
2.9.3.1.2.1 PackageInstallerSession.addClientProgress 1 2 3 4 5 6 7 @Override public void addClientProgress (float progress) { synchronized (mLock) { setClientProgress(mClientProgress + progress); } }
2.9.3.1.2.2 PackageInstallerSession.setClientProgress 1 2 3 4 5 6 7 8 9 10 @Override public void setClientProgress (float progress) { synchronized (mLock) { final boolean forcePublish = (mClientProgress == 0 ); mClientProgress = progress; computeProgressLocked(forcePublish); } }
2.9.3.1.2.3 PackageInstallerSession.computeProgressLocked 1 2 3 4 5 6 7 8 9 10 11 private void computeProgressLocked (boolean forcePublish) { mProgress = MathUtils.constrain(mClientProgress * 0.8f , 0f , 0.8f ) + MathUtils.constrain(mInternalProgress * 0.2f , 0f , 0.2f ); if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01 ) { mReportedProgress = mProgress; mCallback.onSessionProgressChanged(this , mProgress); } }
逻辑很简单,这里就不多说了!
2.9.4 Pm.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 31 private int doCommitSession (int sessionId, boolean logSuccess) throws RemoteException { PackageInstaller.Session session = null ; try { session = new PackageInstaller.Session( mInstaller.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) { System.out.println("Success" ); } } else { System.err.println("Failure [" + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]" ); } return status; } finally { IoUtils.closeQuietly(session); } }
到这里,提交过程就结束了,最终的逻辑是在 PackageInstallerService 中实现!
2.9.4.1 new LocalIntentReceiver - 跨进程返回结果 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); } } }; ... ... ...
LocalIntentReceiver 有一个内部成员 mLocalSender,实现了 IIntentSender.Stub,用于跨进程通信!
系统进程会持有 mLocalSender 对应的代理对象,通过 send 方法,将安装的状态或者结果返回保存到 mResult 中!
2.9.4.2 LocalIntentReceiver.getIntentSender getIntentSender 将 getIntentSender 封装到 IntentSender 中,由于 IntentSender 实现了 Parcelable,所以可以跨进程传递:
1 2 3 public IntentSender getIntentSender () { return new IntentSender((IIntentSender) mLocalSender); }
2.9.4.3 Session.commit 1 2 3 4 5 6 7 8 public void commit (@NonNull IntentSender statusReceiver) { try { mSession.commit(statusReceiver); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
继续来看:
2.9.4.4 LocalIntentReceiver.getResult getResult 用于获得安装结果!
1 2 3 4 5 6 7 8 public Intent getResult () { try { return mResult.take(); } catch (InterruptedException e) { throw new RuntimeException(e); } }
就先分析到这里:
#3 PackageInstallerService
下面来分析下 PackageInstallerService 中的逻辑,我们先来看看 PackageInstallerService 的创建,当然,这部分的逻辑是在开机的时候,这里我们再回顾下:
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 public PackageInstallerService (Context context, PackageManagerService pm) { mContext = context; mPm = pm; mInstallThread = new HandlerThread(TAG); mInstallThread.start(); mInstallHandler = new Handler(mInstallThread.getLooper()); mCallbacks = new Callbacks(mInstallThread.getLooper()); mSessionsFile = new AtomicFile( new File(Environment.getDataSystemDirectory(), "install_sessions.xml" )); mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions" ); mSessionsDir.mkdirs(); synchronized (mSessions) { readSessionsLocked(); reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL, false ); reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL, true ); final ArraySet<File> unclaimedIcons = newArraySet( mSessionsDir.listFiles()); for (int i = 0 ; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); unclaimedIcons.remove(buildAppIconFile(session.sessionId)); } for (File icon : unclaimedIcons) { Slog.w(TAG, "Deleting orphan icon " + icon); icon.delete(); } } }
关于 PackageInstallerService 这里就不在过多分析,我们继续看!!
3.1 PackageInstallerS.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 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; }
3.1.1 PackageInstallerS.getSessionCount 获得 installerUid 创建的 Session 总数:
1 2 3 4 5 6 7 8 9 10 11 12 13 private static int getSessionCount (SparseArray<PackageInstallerSession> sessions, int installerUid) { int count = 0 ; final int size = sessions.size(); for (int i = 0 ; i < size; i++) { final PackageInstallerSession session = sessions.valueAt(i); if (session.installerUid == installerUid) { count++; } } return count; }
PackageInstallerService 有两个 SparseBooleanArray 成员变量:
1 2 @GuardedBy ("mSessions" )private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
mSessions 保存了所有正在处理的 Session 实例,下标为创建事务的 uid,值为 PackageInstallerSession 是对 Session 的封装!
1 2 3 @GuardedBy ("mSessions" )private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>();
mHistoricalSessions 保存了所有已经处理的 Session 实例,下标为创建事务的 uid,值为 PackageInstallerSession 是对 Session 的封装!
###3.1.2 PackageInstallerS.allocateSessionIdLocked
allocateSessionIdLocked 方法用于给新的 Session 分配 id!
1 2 3 4 5 6 7 8 9 10 11 12 13 private int allocateSessionIdLocked () { int n = 0 ; int sessionId; do { sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1 ) + 1 ; if (!mAllocatedSessions.get(sessionId, false )) { mAllocatedSessions.put(sessionId, true ); return sessionId; } } while (n++ < 32 ); throw new IllegalStateException("Failed to allocate session ID" ); }
PackageInstallerService 还有一个 SparseBooleanArray 成员变量:
1 2 3 @GuardedBy ("mSessions" )private final SparseBooleanArray mAllocatedSessions = new SparseBooleanArray();
mAllocatedSessions 保存了所有的 Session 实例,包括正在处理和已经处理的(mSessions 和 mHistoricalSessions),下标为创建事务的 uid,值为 PackageInstallerSession 是对 Session 的封装!
3.1.3 PackageInstallerS.buildStageDir 1 2 3 4 private File buildStageDir (String volumeUuid, int sessionId, boolean isEphemeral) { final File stagingDir = buildStagingDir(volumeUuid, isEphemeral); return new File(stagingDir, "vmdl" + sessionId + ".tmp" ); }
我们可以看到,在安装时,创建的临时文件目录是 /data/app/vmdl[sessionId].tmp!!
3.1.3.1 PackageInstallerS.buildStagingDir buildStagingDir 用于返回文件根目录!
1 2 3 4 5 6 7 8 private File buildStagingDir (String volumeUuid, boolean isEphemeral) { if (isEphemeral) { return Environment.getDataAppEphemeralDirectory(volumeUuid); } return Environment.getDataAppDirectory(volumeUuid); }
3.1.4 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 62 63 64 65 66 67 68 69 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,因此其还可以作为服务端的桩对象,进行跨进程的通信!
这里的 DEFAULT_CONTAINER_PACKAGE 是一个字符串常量:1 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer" ;
3.1.4.1 new InternalCallback 在创建 PackageInstallerSession 时,我们传入了一个回调对象 InternalCallback:
1 private final InternalCallback mInternalCallback = new InternalCallback();
InternalCallback 类定义在 PackageInstallerService 中:
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 class InternalCallback { public void onSessionBadgingChanged (PackageInstallerSession session) { mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId); writeSessionsAsync(); } public void onSessionActiveChanged (PackageInstallerSession session, boolean active) { mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId, active); } public void onSessionProgressChanged (PackageInstallerSession session, float progress) { mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); } public void onSessionFinished (final PackageInstallerSession session, boolean success) { mCallbacks.notifySessionFinished(session.sessionId, session.userId, success); mInstallHandler.post(new Runnable() { @Override public void run () { synchronized (mSessions) { mSessions.remove(session.sessionId); mHistoricalSessions.put(session.sessionId, session); final File appIconFile = buildAppIconFile(session.sessionId); if (appIconFile.exists()) { appIconFile.delete(); } writeSessionsLocked(); } } }); } public void onSessionPrepared (PackageInstallerSession session) { writeSessionsAsync(); } public void onSessionSealedBlocking (PackageInstallerSession session) { synchronized (mSessions) { writeSessionsLocked(); } } }
可以看到,当 Session 的状态发生变化后,InternalCallback 回调会触发!
同时会回调 mCallbacks 的一些接口,而 mCallbacks 是在 PackageInstallerService 中创建的:
1 2 3 4 5 6 public PackageInstallerService (Context context, PackageManagerService pm) { ... ... ... mCallbacks = new Callbacks(mInstallThread.getLooper()); ... ... ... }
我们来看下 Callbacks 的逻辑!
3.1.4.1.1 new Callbacks Callbacks 是 Handler 的子类,持有子线程 mInstallThread 的 looper,Callbacks 是在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private static class Callbacks extends Handler { private static class Callbacks extends Handler { private static final int MSG_SESSION_CREATED = 1 ; private static final int MSG_SESSION_BADGING_CHANGED = 2 ; private static final int MSG_SESSION_ACTIVE_CHANGED = 3 ; private static final int MSG_SESSION_PROGRESS_CHANGED = 4 ; private static final int MSG_SESSION_FINISHED = 5 ; private final RemoteCallbackList<IPackageInstallerCallback> mCallbacks = new RemoteCallbackList<>(); public Callbacks (Looper looper) { super (looper); }
Callbacks 内部有一个 list,保存了所有监听 Session 状态变化的观察者,同时提供了 register 接口,动态注册观察者!1 2 3 4 5 6 7 public void register (IPackageInstallerCallback callback, int userId) { mCallbacks.register(callback, new UserHandle(userId)); } public void unregister (IPackageInstallerCallback callback) { mCallbacks.unregister(callback); }
Callbacks 内部有如下的 notify 接口,来通知 Session 的状态变化!
3.1.4.1.2 Callbacks.notifySessionXXXX 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private void notifySessionCreated (int sessionId, int userId) { obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget(); } private void notifySessionBadgingChanged (int sessionId, int userId) { obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget(); } private void notifySessionActiveChanged (int sessionId, int userId, boolean active) { obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, userId, active).sendToTarget(); } private void notifySessionProgressChanged (int sessionId, int userId, float progress) { obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget(); } public void notifySessionFinished (int sessionId, int userId, boolean success) { obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget(); } }
本质上是发送不同的 msg,下面来看看:
3.1.4.1.3 Callbacks.handleMessage 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override public void handleMessage (Message msg) { final int userId = msg.arg2; final int n = mCallbacks.beginBroadcast(); for (int i = 0 ; i < n; i++) { final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i); final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i); if (userId == user.getIdentifier()) { try { invokeCallback(callback, msg); } catch (RemoteException ignored) { } } } mCallbacks.finishBroadcast(); }
最后调用了 invokeCallback,其实可以看到 IPackageInstallerCallback 针对于不同的消息也有不同的接口:
3.1.4.1.4 Callbacks.invokeCallback 继续分析:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void invokeCallback (IPackageInstallerCallback callback, Message msg) throws RemoteException { final int sessionId = msg.arg1; switch (msg.what) { case MSG_SESSION_CREATED: callback.onSessionCreated(sessionId); break ; case MSG_SESSION_BADGING_CHANGED: callback.onSessionBadgingChanged(sessionId); break ; case MSG_SESSION_ACTIVE_CHANGED: callback.onSessionActiveChanged(sessionId, (boolean ) msg.obj); break ; case MSG_SESSION_PROGRESS_CHANGED: callback.onSessionProgressChanged(sessionId, (float ) msg.obj); break ; case MSG_SESSION_FINISHED: callback.onSessionFinished(sessionId, (boolean ) msg.obj); break ; } }
这里我们先分析到这里!
3.1.6 PackageInstallerS.writeSessionsAsync - 持久化事务 1 2 3 4 5 6 7 8 9 10 11 private void writeSessionsAsync () { IoThread.getHandler().post(new Runnable() { @Override public void run () { synchronized (mSessions) { writeSessionsLocked(); } } }); }
3.1.6.1 PackageInstallerS.writeSessionsLocked mSessionsFile 在 PackageInstallerService 构造器中有见过:/data/system/install_sessions.xml!!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 private void writeSessionsLocked () { if (LOGD) Slog.v(TAG, "writeSessionsLocked()" ); FileOutputStream fos = null ; try { fos = mSessionsFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); out.setOutput(fos, StandardCharsets.UTF_8.name()); out.startDocument(null , true ); out.startTag(null , TAG_SESSIONS); final int size = mSessions.size(); for (int i = 0 ; i < size; i++) { final PackageInstallerSession session = mSessions.valueAt(i); writeSessionLocked(out, session); } out.endTag(null , TAG_SESSIONS); out.endDocument(); mSessionsFile.finishWrite(fos); } catch (IOException e) { if (fos != null ) { mSessionsFile.failWrite(fos); } } }
3.1.6.2 PackageInstallerS.writeSessionLocked 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 private void writeSessionLocked (XmlSerializer out, PackageInstallerSession session) throws IOException { final SessionParams params = session.params; out.startTag(null , TAG_SESSION); writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId); writeIntAttribute(out, ATTR_USER_ID, session.userId); writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME, session.installerPackageName); writeIntAttribute(out, ATTR_INSTALLER_UID, session.installerUid); writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis); if (session.stageDir != null ) { writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, session.stageDir.getAbsolutePath()); } if (session.stageCid != null ) { writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid); } writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared()); writeBooleanAttribute(out, ATTR_SEALED, session.isSealed()); writeIntAttribute(out, ATTR_MODE, params.mode); writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags); writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation); writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes); writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName); writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel); writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri); writeIntAttribute(out, ATTR_ORIGINATING_UID, params.originatingUid); writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri); writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride); writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid); final File appIconFile = buildAppIconFile(session.sessionId); if (params.appIcon == null && appIconFile.exists()) { appIconFile.delete(); } else if (params.appIcon != null && appIconFile.lastModified() != params.appIconLastModified) { if (LOGD) Slog.w(TAG, "Writing changed icon " + appIconFile); FileOutputStream os = null ; try { os = new FileOutputStream(appIconFile); params.appIcon.compress(CompressFormat.PNG, 90 , os); } catch (IOException e) { Slog.w(TAG, "Failed to write icon " + appIconFile + ": " + e.getMessage()); } finally { IoUtils.closeQuietly(os); } params.appIconLastModified = appIconFile.lastModified(); } writeGrantedRuntimePermissions(out, params.grantedRuntimePermissions); out.endTag(null , TAG_SESSION); }
3.1.6.3 PackageInstallerS.writeGrantedRuntimePermissions 1 2 3 4 5 6 7 8 9 10 private static void writeGrantedRuntimePermissions (XmlSerializer out, String[] grantedRuntimePermissions) throws IOException { if (grantedRuntimePermissions != null ) { for (String permission : grantedRuntimePermissions) { out.startTag(null , TAG_GRANTED_RUNTIME_PERMISSION); writeStringAttribute(out, ATTR_NAME, permission); out.endTag(null , TAG_GRANTED_RUNTIME_PERMISSION); } } }
3.2 PackageInstallerS.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); } }
3.2.1 PackageInstallerS.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; } }
3.2.2 PackageInstallerS.isCallingUidOwner 1 2 3 4 5 6 7 8 9 10 private boolean isCallingUidOwner (PackageInstallerSession session) { final int callingUid = Binder.getCallingUid(); if (callingUid == Process.ROOT_UID) { return true ; } else { return (session != null ) && (callingUid == session.installerUid); } }
3.3 PackageInstallerS.getSessionInfo - 获得事务 getSessionInfo 方法也是获得 id 对应的 Session 实例,但是封装的结果不同!
1 2 3 4 5 6 7 8 @Override public SessionInfo getSessionInfo (int sessionId) { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); return session != null ? session.generateInfo() : null ; } }
3.3.1 PackageInstallerSession.generateInfo PackageInstallerSession 会返回一个 SessionInfo 对象!用于保存 Session 的一些细节信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public SessionInfo generateInfo () { final SessionInfo info = new SessionInfo(); synchronized (mLock) { info.sessionId = sessionId; info.installerPackageName = installerPackageName; info.resolvedBaseCodePath = (mResolvedBaseFile != null ) ? mResolvedBaseFile.getAbsolutePath() : null ; info.progress = mProgress; info.sealed = mSealed; info.active = mActiveCount.get() > 0 ; info.mode = params.mode; info.sizeBytes = params.sizeBytes; info.appPackageName = params.appPackageName; info.appIcon = params.appIcon; info.appLabel = params.appLabel; } return info; }
3.3.2 new PackageInstaller.SessionInfo SessionInfo 定义在 PackageInstaller.java 中,用于保存 Session 的信息,这里我们简单的分析下!
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 public static class SessionInfo implements Parcelable { public int sessionId; public String installerPackageName; public String resolvedBaseCodePath; public float progress; public boolean sealed; public boolean active; public int mode; public long sizeBytes; public String appPackageName; public Bitmap appIcon; public CharSequence appLabel; public SessionInfo () { } public SessionInfo (Parcel source) { sessionId = source.readInt(); installerPackageName = source.readString(); resolvedBaseCodePath = source.readString(); progress = source.readFloat(); sealed = source.readInt() != 0 ; active = source.readInt() != 0 ; mode = source.readInt(); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null ); appLabel = source.readString(); } ... ... ... }
4 PackageInstallerSession 4.1 openWrite 这里的 name 传入的是 base.apk
1 2 3 4 5 6 7 8 9 @Override public ParcelFileDescriptor openWrite (String name, long offsetBytes, long lengthBytes) { try { return openWriteInternal(name, offsetBytes, lengthBytes); } catch (IOException e) { throw ExceptionUtils.wrap(e); } }
4.1.1 openWriteInternal 继续来看,这里的参数 name 传入的是 “base.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 private ParcelFileDescriptor openWriteInternal (String name, long offsetBytes, long lengthBytes) throws IOException { final FileBridge bridge; synchronized (mLock) { assertPreparedAndNotSealed("openWrite" ); bridge = new FileBridge(); mBridges.add(bridge); } try { if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid name: " + name); } final File target; final long identity = Binder.clearCallingIdentity(); try { target = new File(resolveStageDir(), name); } finally { Binder.restoreCallingIdentity(identity); } final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_CREAT | O_WRONLY, 0644 ); Os.chmod(target.getAbsolutePath(), 0644 ); if (lengthBytes > 0 ) { final StructStat stat = Libcore.os.fstat(targetFd); final long deltaBytes = lengthBytes - stat.st_size; if (stageDir != null && deltaBytes > 0 ) { mPm.freeStorage(params.volumeUuid, deltaBytes); } Libcore.os.posix_fallocate(targetFd, 0 , lengthBytes); } if (offsetBytes > 0 ) { Libcore.os.lseek(targetFd, offsetBytes, OsConstants.SEEK_SET); } bridge.setTargetFile(targetFd); bridge.start(); return new ParcelFileDescriptor(bridge.getClientSocket()); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } }
整个方法很简单,不多说了!
4.2 commit - 提交事务核心入口 在上面我们分析到,会进入 PackageInstallerSession.commit 提交事务。下面我们继续来分析!
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 @Override public void commit (IntentSender statusReceiver) { Preconditions.checkNotNull(statusReceiver); final boolean wasSealed; synchronized (mLock) { wasSealed = mSealed; if (!mSealed) { for (FileBridge bridge : mBridges) { if (!bridge.isClosed()) { throw new SecurityException("Files still open" ); } } mSealed = true ; } mClientProgress = 1f ; computeProgressLocked(true ); } if (!wasSealed) { mCallback.onSessionSealedBlocking(this ); } mActiveCount.incrementAndGet(); final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext, statusReceiver, sessionId, mIsInstallerDeviceOwner, userId); mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget(); }
mActiveCount 加 1,表示该事务处于活跃状态,直到安装完成!
这里的 PackageInstallObserverAdapter.getBinder() 返回是一个服务端 Stub 桩对象!
整个流程很清晰,我们继续看:
4.2.1 new PackageInstallObserverAdapter PackageInstallObserverAdapter 定义在 PackageInstallService 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static class PackageInstallObserverAdapter extends PackageInstallObserver { private final Context mContext; private final IntentSender mTarget; private final int mSessionId; private final boolean mShowNotification; private final int mUserId; public PackageInstallObserverAdapter (Context context, IntentSender target, int sessionId, boolean showNotification, int userId) { mContext = context; mTarget = target; mSessionId = sessionId; mShowNotification = showNotification; mUserId = userId; }
PackageInstallObserverAdapter 继承了 PackageInstallObserver:
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 public class PackageInstallObserver { private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired (Intent intent) { PackageInstallObserver.this .onUserActionRequired(intent); } @Override public void onPackageInstalled (String basePackageName, int returnCode, String msg, Bundle extras) { PackageInstallObserver.this .onPackageInstalled(basePackageName, returnCode, msg, extras); } }; public IPackageInstallObserver2 getBinder () { return mBinder; } ... ... ... }
PackageInstallObserverAdapter 继承了 PackageInstallObserver,并覆写了以下两个方法:
1 2 onUserActionRequired onPackageInstalled
4.2.1.1 PackageInstallObserverAdapter.onUserActionRequired 覆写 onUserActionRequired,当安装过程需要用户参与授权时,会回调该接口,此时会中断安装,事务从 active 变为 idle 状态!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Override public void onUserActionRequired (Intent intent) { final Intent fillIn = new Intent(); fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); 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,我们后面会看到!
4.1.1.2 PackageInstallObserverAdapter.onPackageInstalled 覆写 onPackageInstalled,当安装完成后,会回调该接口!
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 @Override public void onPackageInstalled (String basePackageName, int returnCode, String msg, Bundle extras) { if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) { boolean update = (extras != null ) && extras.getBoolean(Intent.EXTRA_REPLACING); Notification notification = buildSuccessNotification(mContext, mContext.getResources() .getString(update ? R.string.package_updated_device_owner : R.string.package_installed_device_owner), basePackageName, mUserId); if (notification != null ) { NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(basePackageName, 0 , notification); } } final Intent fillIn = new Intent(); fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName); fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageManager.installStatusToPublicStatus(returnCode)); fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, PackageManager.installStatusToString(returnCode, msg)); fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); if (extras != null ) { final String existing = extras.getString( PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); if (!TextUtils.isEmpty(existing)) { fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing); } } try { mTarget.sendIntent(mContext, 0 , fillIn, null , null ); } catch (SendIntentException ignored) { } }
我们继续分析!
4.2.2 send MSG_COMMIT 代码片段如下:
1 2 mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
mHandler 的初始化是在 PackageInstallerSession 的构造器中:
1 2 3 4 5 6 7 8 9 10 11 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); ... ... ... }
如果我们直接发送 MSG_COMMIT 消息,回调 mHandlerCallback 会立刻触发:
4.2.2.1 Handler.Callback.handleMessage[MSG_COMMIT] 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 private final Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage (Message msg) { final PackageInfo pkgInfo = mPm.getPackageInfo( params.appPackageName, PackageManager.GET_SIGNATURES , userId); final ApplicationInfo appInfo = mPm.getApplicationInfo( params.appPackageName, 0 , userId); synchronized (mLock) { if (msg.obj != null ) { mRemoteObserver = (IPackageInstallObserver2) msg.obj; } try { commitLocked(pkgInfo, appInfo); } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg); destroyInternal(); dispatchSessionFinished(e.error, completeMsg, null ); } return true ; } } };
PackageInstallerSession 内部有一个 mRemoteObserver 成员变量,后面我们会见到:
1 2 @GuardedBy ("mLock" )private IPackageInstallObserver2 mRemoteObserver;
接下来,进入了 commitLocked 方法!
4.2.3 commitLocked 继续来看:
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 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); }
继续分析:
4.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; } }
逻辑很简单,不多说了!
4.2.3.2 validateInstallLocked 校验安装有效性,这里的 mResolvedStageDir 就是前面的 /data/app/vmdl[sessionId].tmp 目录!
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 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); } } } } } }
总结下:
1、返回 /data/app/vmdl[sessionId].tmp 目录下所有的 .removed 文件,去除后缀,将前缀名保存到 removeSplitList; 2、/data/app/vmdl[sessionId].tmp 目录下必须要有 apk 文件或者 .removed 文件; 3、遍历该目录下的非 .removed 文件,对其 packagename versionCode 和签名做关联校验; 4、stagedSplits 用于保存该目录下的所有 apk 的 splitName,base apk 的 splitName 为 null; 5、mResolvedBaseFile 用于保存 base apk; 6、mResolvedStagedFiles 用于保存目录下所有的 apk;
7、removeSplitList 大于 0,说明有要移除的 split apk,前提是主 apk 要有 split apk!
8、对于 MODE_FULL_INSTALL,全量安装,必须要有 base apk! 9、对于 MODE_INHERIT_EXISTING,继承安装,会再次解析主 apk,收集那些不在 removeSplitList 列表中的 splitApk 路径到 mResolvedInheritedFiles 中;
4.2.3.2.1 assertApkConsistent 校验 apk 的一致性,ApkLite 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 private void assertApkConsistent (String tag, ApkLite apk) throws PackageManagerException { if (!mPackageName.equals(apk.packageName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package " + apk.packageName + " inconsistent with " + mPackageName); } if (params.appPackageName != null && !params.appPackageName.equals(apk.packageName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " specified package " + params.appPackageName + " inconsistent with " + apk.packageName); } if (mVersionCode != apk.versionCode) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " version code " + apk.versionCode + " inconsistent with " + mVersionCode); } if (!Signature.areExactMatch(mSignatures, apk.signatures)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " signatures are inconsistent" ); } }
流程很简单,不多说了!
4.2.3.3 close close 方法很简单,将事务的 mActiveCount 引用计数自减 1,同时回调
1 2 3 4 5 6 7 8 @Override public void close () { if (mActiveCount.decrementAndGet() == 0 ) { mCallback.onSessionActiveChanged(this , false ); } }
4.2.3.4 calculateInstalledSize 用于计算最终的安装大小!
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 long calculateInstalledSize () throws PackageManagerException { Preconditions.checkNotNull(mResolvedBaseFile); final ApkLite baseApk; try { baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0 ); } catch (PackageParserException e) { throw PackageManagerException.from(e); } final List<String> splitPaths = new ArrayList<>(); for (File file : mResolvedStagedFiles) { if (mResolvedBaseFile.equals(file)) continue ; splitPaths.add(file.getAbsolutePath()); } for (File file : mResolvedInheritedFiles) { if (mResolvedBaseFile.equals(file)) continue ; splitPaths.add(file.getAbsolutePath()); } final PackageLite pkg = new PackageLite(null , baseApk, null , splitPaths.toArray(new String[splitPaths.size()]), null ); final boolean isForwardLocked = (params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ; try { return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, params.abiOverride); } catch (IOException e) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Failed to calculate install size" , e); } }
我们去 PackageHelper.calculateInstalledSize 方法中去看看:
4.2.3.4.1 calculateInstalledSize 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 public static long calculateInstalledSize (PackageLite pkg, boolean isForwardLocked, String abiOverride) throws IOException { NativeLibraryHelper.Handle handle = null ; try { handle = NativeLibraryHelper.Handle.create(pkg); return calculateInstalledSize(pkg, handle, isForwardLocked, abiOverride); } finally { IoUtils.closeQuietly(handle); } } public static long calculateInstalledSize (PackageLite pkg, NativeLibraryHelper.Handle handle, boolean isForwardLocked, String abiOverride) throws IOException { long sizeBytes = 0 ; for (String codePath : pkg.getAllCodePaths()) { final File codeFile = new File(codePath); sizeBytes += codeFile.length(); if (isForwardLocked) { sizeBytes += PackageHelper.extractPublicFiles(codeFile, null ); } } sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride); return sizeBytes; }
这里就分析到这里!
4.2.3.5 computeProgressLocked 1 2 3 4 5 6 7 8 9 10 11 private void computeProgressLocked (boolean forcePublish) { mProgress = MathUtils.constrain(mClientProgress * 0.8f , 0f , 0.8f ) + MathUtils.constrain(mInternalProgress * 0.2f , 0f , 0.2f ); if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01 ) { mReportedProgress = mProgress; mCallback.onSessionProgressChanged(this , mProgress); } }
提取本地的 lib 库文件!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private static void extractNativeLibraries (File packageDir, String abiOverride) throws PackageManagerException { final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME); NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true ); NativeLibraryHelper.Handle handle = null ; try { handle = NativeLibraryHelper.Handle.create(packageDir); final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libDir, abiOverride); if (res != PackageManager.INSTALL_SUCCEEDED) { throw new PackageManagerException(res, "Failed to extract native libraries, res=" + res); } } catch (IOException e) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Failed to extract native libraries" , e); } finally { IoUtils.closeQuietly(handle); } }
对于 lib 的提取,这里涉及到了 NativeLibraryHelper,我们先不过多关注其实现!
5 PackageManagerService 5.1 PackageManagerService.installStage 接下来,进入 PackageManagerService 阶段。
这里的 IPackageInstallObserver2 observer 是前面创建的本次 localObserver:
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 void installStage (String packageName, File stagedDir, String stagedCid, IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams, String installerPackageName, int installerUid, UserHandle user, Certificate[][] certificates) { if (DEBUG_EPHEMERAL) { if ((sessionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ) { Slog.d(TAG, "Ephemeral install of " + packageName); } } final VerificationInfo verificationInfo = new VerificationInfo( sessionParams.originatingUri, sessionParams.referrerUri, sessionParams.originatingUid, installerUid); final OriginInfo origin; if (stagedDir != null ) { origin = OriginInfo.fromStagedFile(stagedDir); } else { origin = OriginInfo.fromStagedContainer(stagedCid); } final Message msg = mHandler.obtainMessage(INIT_COPY); final InstallParams params = new InstallParams(origin, null , observer, sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid, verificationInfo, user, sessionParams.abiOverride, sessionParams.grantedRuntimePermissions, certificates); params.setTraceMethod("installStage" ).setTraceCookie(System.identityHashCode(params)); msg.obj = params; Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage" , System.identityHashCode(msg.obj)); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(msg.obj)); mHandler.sendMessage(msg); }
这里的 mHandler 是在 PackageManagerService 的构造器中创建的:
1 2 3 4 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true ); mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper());
是一个 PackageHandler 实例,其绑定了一个子线程 ServiceThread!
5.1.1 new VerificationInfo VerificationInfo 类定义在 PackageManagerService 中,用于信息校验:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static class VerificationInfo { public static final int NO_UID = -1 ; final Uri originatingUri; final Uri referrer; final int originatingUid; final int installerUid; VerificationInfo(Uri originatingUri, Uri referrer, int originatingUid, int installerUid) { this .originatingUri = originatingUri; this .referrer = referrer; this .originatingUid = originatingUid; this .installerUid = installerUid; } }
5.1.2 new OriginInfo 这里创建了一个 OriginInfo 实例,封装安装目录相关信息!
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 static class OriginInfo { final File file; final String cid; final boolean staged; final boolean existing; final String resolvedPath; final File resolvedFile; static OriginInfo fromNothing () { return new OriginInfo(null , null , false , false ); } static OriginInfo fromUntrustedFile (File file) { return new OriginInfo(file, null , false , false ); } static OriginInfo fromExistingFile (File file) { return new OriginInfo(file, null , false , true ); } static OriginInfo fromStagedFile (File file) { return new OriginInfo(file, null , true , false ); } static OriginInfo fromStagedContainer (String cid) { return new OriginInfo(null , cid, true , false ); } private OriginInfo (File file, String cid, boolean staged, boolean existing) { this .file = file; this .cid = cid; this .staged = staged; this .existing = existing; if (cid != null ) { resolvedPath = PackageHelper.getSdDir(cid); resolvedFile = new File(resolvedPath); } else if (file != null ) { resolvedPath = file.getAbsolutePath(); resolvedFile = file; } else { resolvedPath = null ; resolvedFile = null ; } } }
这里我们先关注安装到内置存储中的逻辑!
5.1.3 new PMS.InstallParams InstallParams 类定义在 PackageManagerService 中,封装了安装参数:
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 class InstallParams extends HandlerParams { final OriginInfo origin; final MoveInfo move; final IPackageInstallObserver2 observer; int installFlags; final String installerPackageName; final String volumeUuid; private InstallArgs mArgs; private int mRet; final String packageAbiOverride; final String[] grantedRuntimePermissions; final VerificationInfo verificationInfo; final Certificate[][] certificates; InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, String volumeUuid, VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride, String[] grantedPermissions, Certificate[][] certificates) { super (user); this .origin = origin; this .move = move; this .observer = observer; this .installFlags = installFlags; this .installerPackageName = installerPackageName; this .volumeUuid = volumeUuid; this .verificationInfo = verificationInfo; this .packageAbiOverride = packageAbiOverride; this .grantedRuntimePermissions = grantedPermissions; this .certificates = certificates; } ... ... ... }
InstallParams 继承了 HandlerParams!
这里涉及到一个 MoveInfo move,在 movePackageInternal 也就是移动 package 时才会调用,这里是安装,我们先不关注!
5.2 PackageHandler.doHandleMessage[INIT_COPY] PackageHandler 会在子线程中处理 INIT_COPY 消息:
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 case INIT_COPY: { HandlerParams params = (HandlerParams) msg.obj; int idx = mPendingInstalls.size(); if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params); if (!mBound) { Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS" , System.identityHashCode(mHandler)); if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service" ); params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS" , System.identityHashCode(mHandler)); if (params.traceMethod != null ) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } return ; } else { mPendingInstalls.add(idx, params); } } else { mPendingInstalls.add(idx, params); if (idx == 0 ) { mHandler.sendEmptyMessage(MCS_BOUND); } } break ; }
这里逻辑很清晰了,我们继续看!
5.2.1 PackageHandler.connectToService 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private boolean connectToService () { if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" + " DefaultContainerService" ); Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); mBound = true ; return true ; } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return false ; }
这里 bind 的服务是 DefaultContainerService!1 2 3 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName( DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService" );
PackageManagerService 内部持有一个 DefaultContainerConnection 实例!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection(); class DefaultContainerConnection implements ServiceConnection { public void onServiceConnected (ComponentName name, IBinder service) { if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected" ); IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service); mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs)); } public void onServiceDisconnected (ComponentName name) { if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected" ); } }
最后会发送 MCS_BOUND 消息给 PackageHandler 对象!
5.2.2 InstallParams.serviceError serviceError 方法是从 HandlerParams 中继承到的:
1 2 3 4 5 6 7 final void serviceError () { if (DEBUG_INSTALL) Slog.i(TAG, "serviceError" ); handleServiceError(); handleReturnCode(); }
handleServiceError 方法和 handleReturnCode 方法的最终实现也是在 InstallParams 中!
5.3 PackageHandler.doHandleMessage[MCS_BOUND] - 绑定服务 继续来看下 PackageHandler 对 MCS_BOUND 的处理:
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 case MCS_BOUND: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound" ); if (msg.obj != null ) { mContainerService = (IMediaContainerService) msg.obj; Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS" , System.identityHashCode(mHandler)); } if (mContainerService == null ) { if (!mBound) { Slog.e(TAG, "Cannot bind to media container service" ); for (HandlerParams params : mPendingInstalls) { params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(params)); if (params.traceMethod != null ) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } return ; } mPendingInstalls.clear(); } else { Slog.w(TAG, "Waiting to connect to media container service" ); } } else if (mPendingInstalls.size() > 0 ) { HandlerParams params = mPendingInstalls.get(0 ); if (params != null ) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(params)); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy" ); if (params.startCopy()) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind..." ); if (mPendingInstalls.size() > 0 ) { mPendingInstalls.remove(0 ); } if (mPendingInstalls.size() == 0 ) { if (mBound) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND" ); removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); sendMessageDelayed(ubmsg, 10000 ); } } else { if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting MCS_BOUND for next work" ); mHandler.sendEmptyMessage(MCS_BOUND); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } else { Slog.w(TAG, "Empty queue" ); } break ; }
5.4 InstallParams.startCopy InstallParams 继承了 HandlerParams:
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 final boolean startCopy () { boolean res; try { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this ); if (++mRetries > MAX_RETRIES) { Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up" ); mHandler.sendEmptyMessage(MCS_GIVE_UP); handleServiceError(); return false ; } else { handleStartCopy(); res = true ; } } catch (RemoteException e) { if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT" ); mHandler.sendEmptyMessage(MCS_RECONNECT); res = false ; } handleReturnCode(); return res; }
这里定义了安装尝试次数:1 private static final int MAX_RETRIES = 4 ;
5.4.1 PackageHandler.doHandleMessage[MCS_GIVE_UP] - 放弃安装 重试次数大于 4 ,那么就放弃本次安装!
1 2 3 4 5 6 7 8 case MCS_GIVE_UP: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries" ); HandlerParams params = mPendingInstalls.remove(0 ); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(params)); break ; }
5.4.2 InstallParams.handleServiceError 处理本次安装失败的结果:
1 2 3 4 5 6 @Override void handleServiceError () { mArgs = createInstallArgs(this ); mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; }
这里的 createInstallArgs 方法我们后面再分析!
5.4.3 PackageHandler.doHandleMessage[MCS_RECONNECT] - 重连服务 MCS_RECONNECT 消息会尝试重连服务!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 case MCS_RECONNECT: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect" ); if (mPendingInstalls.size() > 0 ) { if (mBound) { disconnectService(); } if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service" ); for (HandlerParams params : mPendingInstalls) { params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(params)); } mPendingInstalls.clear(); } } break ; }
流程很简单,不多说了!
5.4.4 InstallParams.handleReturnCode 当 mArgs 为 null 的时候,此时该 package 正在被校验,所以需要等到校验成功后才能安装,所以不会进入这里!
1 2 3 4 5 6 7 8 @Override void handleReturnCode () { if (mArgs != null ) { processPendingInstall(mArgs, mRet); } }
我们继续看!
5.5 InstallParams.handleStartCopy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 public void handleStartCopy () throws RemoteException { int ret = PackageManager.INSTALL_SUCCEEDED; if (origin.staged) { if (origin.file != null ) { installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } else if (origin.cid != null ) { installFlags |= PackageManager.INSTALL_EXTERNAL; installFlags &= ~PackageManager.INSTALL_INTERNAL; } else { throw new IllegalStateException("Invalid stage location" ); } } final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ; final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0 ; final boolean ephemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ; PackageInfoLite pkgLite = null ; if (onInt && onSd) { Slog.w(TAG, "Conflicting flags specified for installing on both internal and external" ); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else if (onSd && ephemeral) { Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external" ); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); if (DEBUG_EPHEMERAL && ephemeral) { Slog.v(TAG, "pkgLite for install: " + pkgLite); } if (!origin.staged && pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { final StorageManager storage = StorageManager.from(mContext); final long lowThreshold = storage.getStorageLowBytes( Environment.getDataDirectory()); final long sizeBytes = mContainerService.calculateInstalledSize( origin.resolvedPath, isForwardLocked(), packageAbiOverride); try { mInstaller.freeCache(null , sizeBytes + lowThreshold); pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); } catch (InstallerException e) { Slog.w(TAG, "Failed to free cache" , e); } if (pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INVALID_URI) { pkgLite.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE; } } } if (ret == PackageManager.INSTALL_SUCCEEDED) { int loc = pkgLite.recommendedInstallLocation; if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) { ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) { ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS; } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) { ret = PackageManager.INSTALL_FAILED_INVALID_APK; } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) { ret = PackageManager.INSTALL_FAILED_INVALID_URI; } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) { ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE; } else { loc = installLocationPolicy(pkgLite); if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) { ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; } else if (!onSd && !onInt) { if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { installFlags |= PackageManager.INSTALL_EXTERNAL; installFlags &= ~PackageManager.INSTALL_INTERNAL; } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) { if (DEBUG_EPHEMERAL) { Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag" ); } installFlags |= PackageManager.INSTALL_EPHEMERAL; installFlags &= ~(PackageManager.INSTALL_EXTERNAL |PackageManager.INSTALL_INTERNAL); } else { installFlags |= PackageManager.INSTALL_INTERNAL; installFlags &= ~PackageManager.INSTALL_EXTERNAL; } } } } final InstallArgs args = createInstallArgs(this ); mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { UserHandle verifierUser = getUser(); if (verifierUser == UserHandle.ALL) { verifierUser = UserHandle.SYSTEM; } final int requiredUid = mRequiredVerifierPackage == null ? -1 : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, verifierUser.getIdentifier()); if (!origin.existing && requiredUid != -1 && isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) { final Intent verification = new Intent( Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)), PACKAGE_MIME_TYPE); verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification, PACKAGE_MIME_TYPE, 0 , verifierUser.getIdentifier()); if (DEBUG_VERIFY) { Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent " + verification.toString() + " with " + pkgLite.verifiers.length + " optional verifiers" ); } final int verificationId = mPendingVerificationToken++; verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId); verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE, installerPackageName); verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, installFlags); verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName); verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode); if (verificationInfo != null ) { if (verificationInfo.originatingUri != null ) { verification.putExtra(Intent.EXTRA_ORIGINATING_URI, verificationInfo.originatingUri); } if (verificationInfo.referrer != null ) { verification.putExtra(Intent.EXTRA_REFERRER, verificationInfo.referrer); } if (verificationInfo.originatingUid >= 0 ) { verification.putExtra(Intent.EXTRA_ORIGINATING_UID, verificationInfo.originatingUid); } if (verificationInfo.installerUid >= 0 ) { verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID, verificationInfo.installerUid); } } final PackageVerificationState verificationState = new PackageVerificationState( requiredUid, args); mPendingVerification.append(verificationId, verificationState); final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite, receivers, verificationState); if (sufficientVerifiers != null ) { final int N = sufficientVerifiers.size(); if (N == 0 ) { Slog.i(TAG, "Additional verifiers required, but none installed." ); ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; } else { for (int i = 0 ; i < N; i++) { final ComponentName verifierComponent = sufficientVerifiers.get(i); final Intent sufficientIntent = new Intent(verification); sufficientIntent.setComponent(verifierComponent); mContext.sendBroadcastAsUser(sufficientIntent, verifierUser); } } } final ComponentName requiredVerifierComponent = matchComponentForVerifier( mRequiredVerifierPackage, receivers); if (ret == PackageManager.INSTALL_SUCCEEDED && mRequiredVerifierPackage != null ) { Trace.asyncTraceBegin( TRACE_TAG_PACKAGE_MANAGER, "verification" , verificationId); verification.setComponent(requiredVerifierComponent); mContext.sendOrderedBroadcastAsUser(verification, verifierUser, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, new BroadcastReceiver() { @Override public void onReceive (Context context, Intent intent) { final Message msg = mHandler .obtainMessage(CHECK_PENDING_VERIFICATION); msg.arg1 = verificationId; mHandler.sendMessageDelayed(msg, getVerificationTimeout()); } }, null , 0 , null , null ); mArgs = null ; } } else { ret = args.copyApk(mContainerService, true ); } } mRet = ret; }
直接可以看到,最终
5.5.1 DefaultContainerService.getMinimalPackageInfo getMinimalPackageInfo 方法会解析 apk,返回 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 @Override public PackageInfoLite getMinimalPackageInfo (String packagePath, int flags, String abiOverride) { final Context context = DefaultContainerService.this ; final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ; PackageInfoLite ret = new PackageInfoLite(); if (packagePath == null ) { Slog.i(TAG, "Invalid package file " + packagePath); ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; return ret; } final File packageFile = new File(packagePath); final PackageParser.PackageLite pkg; final long sizeBytes; try { pkg = PackageParser.parsePackageLite(packageFile, 0 ); sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride); } catch (PackageParserException | IOException e) { Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e); if (!packageFile.exists()) { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI; } else { ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; } return ret; } ret.packageName = pkg.packageName; ret.splitNames = pkg.splitNames; ret.versionCode = pkg.versionCode; ret.baseRevisionCode = pkg.baseRevisionCode; ret.splitRevisionCodes = pkg.splitRevisionCodes; ret.installLocation = pkg.installLocation; ret.verifiers = pkg.verifiers; ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context, pkg.packageName, pkg.installLocation, sizeBytes, flags); ret.multiArch = pkg.multiArch; return ret; }
5.5.1.1 new PackageInfoLite PackageInfoLite 用来保存解析到的 apk 的一些信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class PackageInfoLite implements Parcelable { public String packageName; public String[] splitNames; public int versionCode; public int baseRevisionCode; public int [] splitRevisionCodes; public boolean multiArch; public int recommendedInstallLocation; public int installLocation; public VerifierInfo[] verifiers; public PackageInfoLite () { } ... ... ... }
这里的 recommendedInstallLocation 可以取下面四个值:
1 2 3 4 PackageHelper.RECOMMEND_INSTALL_INTERNAL PackageHelper.RECOMMEND_INSTALL_EXTERNAL PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE PackageHelper.RECOMMEND_FAILED_INVALID_APK
5.5.1.2 PackageHelper.resolveInstallLocation resolveInstallLocation 方法用于计算一个合适的安装位置给 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 public static int resolveInstallLocation (Context context, String packageName, int installLocation, long sizeBytes, int installFlags) { ApplicationInfo existingInfo = null ; try { existingInfo = context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); } catch (NameNotFoundException ignored) { } final int prefer; final boolean checkBoth; boolean ephemeral = false ; if ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ) { prefer = RECOMMEND_INSTALL_INTERNAL; ephemeral = true ; checkBoth = false ; } else if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0 ) { prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false ; } else if ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ) { prefer = RECOMMEND_INSTALL_EXTERNAL; checkBoth = false ; } else if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false ; } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) { prefer = RECOMMEND_INSTALL_EXTERNAL; checkBoth = true ; } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) { if (existingInfo != null ) { if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ) { prefer = RECOMMEND_INSTALL_EXTERNAL; } else { prefer = RECOMMEND_INSTALL_INTERNAL; } } else { prefer = RECOMMEND_INSTALL_INTERNAL; } checkBoth = true ; } else { prefer = RECOMMEND_INSTALL_INTERNAL; checkBoth = false ; } boolean fitsOnInternal = false ; if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) { fitsOnInternal = fitsOnInternal(context, sizeBytes); } boolean fitsOnExternal = false ; if (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL) { fitsOnExternal = fitsOnExternal(context, sizeBytes); } if (prefer == RECOMMEND_INSTALL_INTERNAL) { if (fitsOnInternal) { return (ephemeral) ? PackageHelper.RECOMMEND_INSTALL_EPHEMERAL : PackageHelper.RECOMMEND_INSTALL_INTERNAL; } } else if (prefer == RECOMMEND_INSTALL_EXTERNAL) { if (fitsOnExternal) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } } if (checkBoth) { if (fitsOnInternal) { return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else if (fitsOnExternal) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } } return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE; }
整个过程很简单,不多说了!
5.5.2 PackageManagerS.installLocationPolicy PackageInfoLite pkgLite 保存了本次要安装的应用的信息!
installLocationPolicy 方法会对降级安装和替换安装做一个校验和判断!
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 private int installLocationPolicy (PackageInfoLite pkgLite) { String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ; synchronized (mPackages) { PackageParser.Package installedPkg = mPackages.get(packageName); PackageParser.Package dataOwnerPkg = installedPkg; if (dataOwnerPkg == null ) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null ) { dataOwnerPkg = ps.pkg; } } if (dataOwnerPkg != null ) { final boolean downgradeRequested = (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0 ; final boolean packageDebuggable = (dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 ; final boolean downgradePermitted = (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable)); if (!downgradePermitted) { try { checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) { Slog.w(TAG, "Downgrade detected: " + e.getMessage()); return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE; } } } if (installedPkg != null ) { if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0 ) { if ((installedPkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ) { if (onSd) { Slog.w(TAG, "Cannot install update to system app on sdcard" ); return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION; } return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else { if (onSd) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) { } else { if (isExternal(installedPkg)) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } } } else { return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS; } } } if (onSd) { return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; } return pkgLite.recommendedInstallLocation; }
5.5.3 PackageManagerS.createInstallArgs 其实就是针对不同的安装方式,创建不同的 InstallArgs!
1 2 3 4 5 6 7 8 9 10 11 12 private InstallArgs createInstallArgs (InstallParams params) { if (params.move != null ) { return new MoveInstallArgs(params); } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) { return new AsecInstallArgs(params); } else { return new FileInstallArgs(params); } }
这里我们先关注一般情况,即创建 FileInstallArgs 实例的情况!
5.5.3.1 new FileInstallArgs - 要安装的 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 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 有两个构造器!
当然,这里我们重点关注安装过程!
5.5.4 PackageManagerService.isVerificationEnabled isVerificationEnabled 用于校验系统是否打开了校验功能!
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 boolean isVerificationEnabled (int userId, int installFlags) { if (!DEFAULT_VERIFY_ENABLE) { return false ; } if ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ) { if (DEBUG_EPHEMERAL) { Slog.d(TAG, "INSTALL_EPHEMERAL so skipping verification" ); } return false ; } boolean ensureVerifyAppsEnabled = isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS); if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0 ) { if (ActivityManager.isRunningInTestHarness()) { return false ; } if (ensureVerifyAppsEnabled) { return true ; } if (android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1 ) == 0 ) { return false ; } } if (ensureVerifyAppsEnabled) { return true ; } return android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1 ) == 1 ; }
就不多说了!
5.5.5 new PackageVerificationState PackageVerificationState 用于保存被安装的应用的校验状态信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class PackageVerificationState { private final InstallArgs mArgs; private final SparseBooleanArray mSufficientVerifierUids; private final int mRequiredVerifierUid; private boolean mSufficientVerificationComplete; private boolean mSufficientVerificationPassed; private boolean mRequiredVerificationComplete; private boolean mRequiredVerificationPassed; private boolean mExtendedTimeout; public PackageVerificationState (int requiredVerifierUid, InstallArgs args) { mRequiredVerifierUid = requiredVerifierUid; mArgs = args; mSufficientVerifierUids = new SparseBooleanArray(); mExtendedTimeout = false ; }
不多说了!
5.6 PackageHandler.doHandleMessage[CHECK_PENDING_VERIFICATION] - 校验完成 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 case CHECK_PENDING_VERIFICATION: { final int verificationId = msg.arg1; final PackageVerificationState state = mPendingVerification.get(verificationId); if ((state != null ) && !state.timeoutExtended()) { final InstallArgs args = state.getInstallArgs(); final Uri originUri = Uri.fromFile(args.origin.resolvedFile); Slog.i(TAG, "Verification timed out for " + originUri); mPendingVerification.remove(verificationId); int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE; if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) { Slog.i(TAG, "Continuing with installation of " + originUri); state.setVerifierResponse(Binder.getCallingUid(), PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT); broadcastPackageVerified(verificationId, originUri, PackageManager.VERIFICATION_ALLOW, state.getInstallArgs().getUser()); try { ret = args.copyApk(mContainerService, true ); } catch (RemoteException e) { Slog.e(TAG, "Could not contact the ContainerService" ); } } else { broadcastPackageVerified(verificationId, originUri, PackageManager.VERIFICATION_REJECT, state.getInstallArgs().getUser()); } Trace.asyncTraceEnd( TRACE_TAG_PACKAGE_MANAGER, "verification" , verificationId); processPendingInstall(args, ret); mHandler.sendEmptyMessage(MCS_UNBIND); } break ; }
这里我们通过 getDefaultVerificationResponse 方法返回校验结果:1 2 3 4 5 private int getDefaultVerificationResponse () { return android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE, DEFAULT_VERIFICATION_RESPONSE); }
默认返回的是 PackageManager.VERIFICATION_ALLOW,比如在校验超时的情况下!
5.6.1 PackageManagerS.broadcastPackageVerified 1 2 3 4 5 6 7 8 9 10 11 private void broadcastPackageVerified (int verificationId, Uri packageUri, int verificationCode, UserHandle user) { final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED); intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId); intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode); mContext.sendBroadcastAsUser(intent, user, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT); }
5.6.2 FileInstallArgs.(do)copyApk 1 2 3 4 5 6 7 8 int copyApk (IMediaContainerService imcs, boolean temp) throws RemoteException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk" ); try { return doCopyApk(imcs, temp); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } }
copyApk 调用了 doCopyApk 方法:
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 private int doCopyApk (IMediaContainerService imcs, boolean temp) throws RemoteException { if (origin.staged) { if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy" ); codeFile = origin.file; resourceFile = origin.file; return PackageManager.INSTALL_SUCCEEDED; } try { final boolean isEphemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ; final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral); codeFile = tempDir; resourceFile = tempDir; } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() { @Override public ParcelFileDescriptor open (String name, int mode) throws RemoteException { if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid filename: " + name); } try { final File file = new File(codeFile, name); final FileDescriptor fd = Os.open(file.getAbsolutePath(), O_RDWR | O_CREAT, 0644 ); Os.chmod(file.getAbsolutePath(), 0644 ); return new ParcelFileDescriptor(fd); } catch (ErrnoException e) { throw new RemoteException("Failed to open: " + e.getMessage()); } } }; int ret = PackageManager.INSTALL_SUCCEEDED; ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Failed to copy package" ); return ret; } final File libraryRoot = new File(codeFile, LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null ; try { handle = NativeLibraryHelper.Handle.create(codeFile); ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, abiOverride); } catch (IOException e) { Slog.e(TAG, "Copying native libraries failed" , e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } finally { IoUtils.closeQuietly(handle); } return ret; }
根据前面创建 OriginInfo 时知道:
1 2 3 4 5 if (stagedDir != null ) { origin = OriginInfo.fromStagedFile(stagedDir); } else { origin = OriginInfo.fromStagedContainer(stagedCid); }
通过 adb 安装时,安装到内置存储,会调用 OriginInfo.fromStagedFile 方法,此时 OriginInfo.staged 为 true,安装到外置存储时, OriginInfo.staged 也会为 true。
这是因为在进行 adb install 过程中时,我们通过 Session,已经拷贝到目标目录了:/data/app/vml[sessionId].tmp/,所以这里 doCopyApk 无需在继续进行下去!!
对于其他的安装方式,OriginInfo.staged 为 false 的,那么会进入 doCopyApk 的下一步!
5.6.2.1 PackageInstallerService.allocateStageDirLegacy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Deprecated public File allocateStageDirLegacy (String volumeUuid, boolean isEphemeral) throws IOException { synchronized (mSessions) { try { final int sessionId = allocateSessionIdLocked(); mLegacySessions.put(sessionId, true ); final File stageDir = buildStageDir(volumeUuid, sessionId, isEphemeral); prepareStageDir(stageDir); return stageDir; } catch (IllegalStateException e) { throw new IOException(e); } } }
这里,前面分析过,这里就不多说了!
5.6.2.2 DefaultContainerService.copyPackage(Inner) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public int copyPackage (String packagePath, IParcelFileDescriptorFactory target) { if (packagePath == null || target == null ) { return PackageManager.INSTALL_FAILED_INVALID_URI; } PackageLite pkg = null ; try { final File packageFile = new File(packagePath); pkg = PackageParser.parsePackageLite(packageFile, 0 ); return copyPackageInner(pkg, target); } catch (PackageParserException | IOException | RemoteException e) { Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } }
这里继续调用了 copyPackageInner 方法1 2 3 4 5 6 7 8 9 10 11 12 private int copyPackageInner (PackageLite pkg, IParcelFileDescriptorFactory target) throws IOException, RemoteException { copyFile(pkg.baseCodePath, target, "base.apk" ); if (!ArrayUtils.isEmpty(pkg.splitNames)) { for (int i = 0 ; i < pkg.splitNames.length; i++) { copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk" ); } } return PackageManager.INSTALL_SUCCEEDED; }
最终,调用了 copyFile 执行 copy!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void copyFile (String sourcePath, IParcelFileDescriptorFactory target, String targetName) throws IOException, RemoteException { Slog.d(TAG, "Copying " + sourcePath + " to " + targetName); InputStream in = null ; OutputStream out = null ; try { in = new FileInputStream(sourcePath); out = new ParcelFileDescriptor.AutoCloseOutputStream( target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE)); Streams.copy(in, out); } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); } }
到这里就结束了!
5.7 PackageManagerS.processPendingInstall processPendingInstall 用于继续安装:
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 private void processPendingInstall (final InstallArgs args, final int currentStatus) { mHandler.post(new Runnable() { public void run () { mHandler.removeCallbacks(this ); PackageInstalledInfo res = new PackageInstalledInfo(); res.setReturnCode(currentStatus); res.uid = -1 ; res.pkg = null ; res.removedInfo = null ; if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { args.doPreInstall(res.returnCode); synchronized (mInstallLock) { installPackageTracedLI(args, res); } args.doPostInstall(res.returnCode, res.uid); } final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null ; final int flags = (res.pkg == null ) ? 0 : res.pkg.applicationInfo.flags; boolean doRestore = !update && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0 ); int token; if (mNextInstallToken < 0 ) mNextInstallToken = 1 ; token = mNextInstallToken++; PostInstallData data = new PostInstallData(args, res); mRunningInstalls.put(token, data); if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) { IBackupManager bm = IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); if (bm != null ) { if (DEBUG_INSTALL) Log.v(TAG, "token " + token + " to BM for possible restore" ); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore" , token); try { if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) { bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token); } else { doRestore = false ; } } catch (RemoteException e) { } catch (Exception e) { Slog.e(TAG, "Exception trying to enqueue restore" , e); doRestore = false ; } } else { Slog.e(TAG, "Backup Manager not found!" ); doRestore = false ; } } if (!doRestore) { if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall" , token); Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0 ); mHandler.sendMessage(msg); } } }); }
5.7.1 new PackageInstalledInfo PackageInstalledInfo 用于保存该应用的安装结果信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 static class PackageInstalledInfo { String name; int uid; int [] origUsers; int [] newUsers; PackageParser.Package pkg; int returnCode; String returnMsg; PackageRemovedInfo removedInfo; ArrayMap<String, PackageInstalledInfo> addedChildPackages; ... ... ... String origPackage; String origPermission; }
我们先看到这里!
5.7.1.1 new 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; ... ... ... }
5.7.2 FileInstallArgs.doPreInstall 安装前执行清理操作,正常情况不会触发!1 2 3 4 5 6 7 8 int doPreInstall (int status) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); } return status; }
5.7.2.1 FileInstallArgs.cleanUp(ResourcesLI) 清理操作!1 2 3 4 5 6 7 8 9 10 11 12 13 private boolean cleanUp () { if (codeFile == null || !codeFile.exists()) { return false ; } removeCodePathLI(codeFile); if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) { resourceFile.delete(); } return true ; }
可以看到,最后调用了 removeCodePathLI 方法!1 2 3 4 5 6 7 8 9 10 11 void removeCodePathLI (File codePath) { if (codePath.isDirectory()) { try { mInstaller.rmPackageDir(codePath.getAbsolutePath()); } catch (InstallerException e) { Slog.w(TAG, "Failed to remove code path" , e); } } else { codePath.delete(); } }
5.7.3 PackageManagerS.installPackageTracedLI - 核心安装入口 1 2 3 4 5 6 7 8 9 private void installPackageTracedLI (InstallArgs args, PackageInstalledInfo res) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage" ); installPackageLI(args, res); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } }
这里调用了 installPackageLI 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 private void installPackageLI (InstallArgs args, PackageInstalledInfo res) { final int installFlags = args.installFlags; final String installerPackageName = args.installerPackageName; final String volumeUuid = args.volumeUuid; final File tmpPackageFile = new File(args.getCodePath()); final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ); final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0 ) || (args.volumeUuid != null )); final boolean ephemeral = ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0 ); final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0 ); boolean replace = false ; int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE; if (args.move != null ) { scanFlags |= SCAN_INITIAL; } if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0 ) { scanFlags |= SCAN_DONT_KILL_APP; } res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile); if (ephemeral && (forwardLocked || onExternal)) { Slog.i(TAG, "Incompatible ephemeral install; fwdLocked=" + forwardLocked + " external=" + onExternal); res.setReturnCode(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID); return ; } final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0 ) | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0 ) | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0 ) | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0 ); PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setDisplayMetrics(mMetrics); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage" ); final PackageParser.Package pkg; try { pkg = pp.parsePackage(tmpPackageFile, parseFlags); } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI" , e); return ; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } if (pkg.childPackages != null ) { synchronized (mPackages) { final int childCount = pkg.childPackages.size(); for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); PackageInstalledInfo childRes = new PackageInstalledInfo(); childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED); childRes.pkg = childPkg; childRes.name = childPkg.packageName; PackageSetting childPs = mSettings.peekPackageLPr(childPkg.packageName); if (childPs != null ) { childRes.origUsers = childPs.queryInstalledUsers( sUserManager.getUserIds(), true ); } if ((mPackages.containsKey(childPkg.packageName))) { childRes.removedInfo = new PackageRemovedInfo(); childRes.removedInfo.removedPackage = childPkg.packageName; } if (res.addedChildPackages == null ) { res.addedChildPackages = new ArrayMap<>(); } res.addedChildPackages.put(childPkg.packageName, childRes); } } } if (TextUtils.isEmpty(pkg.cpuAbiOverride)) { pkg.cpuAbiOverride = args.abiOverride; } String pkgName = res.name = pkg.packageName; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0 ) { if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0 ) { res.setError(INSTALL_FAILED_TEST_ONLY, "installPackageLI" ); return ; } } try { if (args.certificates != null ) { try { PackageParser.populateCertificates(pkg, args.certificates); } catch (PackageParserException e) { PackageParser.collectCertificates(pkg, parseFlags); } } else { PackageParser.collectCertificates(pkg, parseFlags); } } catch (PackageParserException e) { res.setError("Failed collect during installPackageLI" , e); return ; } pp = null ; String oldCodePath = null ; boolean systemApp = false ; synchronized (mPackages) { if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0 ) { String oldName = mSettings.mRenamedPackages.get(pkgName); if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName) && mPackages.containsKey(oldName)) { pkg.setPackageName(oldName); pkgName = pkg.packageName; replace = true ; if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName=" + oldName + " pkgName=" + pkgName); } else if (mPackages.containsKey(pkgName)) { replace = true ; if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); } if (pkg.parentPackage != null ) { res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, "Package " + pkg.packageName + " is child of package " + pkg.parentPackage.parentPackage + ". Child packages " + "can be updated only through the parent package." ); return ; } if (replace) { PackageParser.Package oldPackage = mPackages.get(pkgName); final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion; final int newTargetSdk = pkg.applicationInfo.targetSdkVersion; if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1 && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) { res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE, "Package " + pkg.packageName + " new target SDK " + newTargetSdk + " doesn't support runtime permissions but the old" + " target SDK " + oldTargetSdk + " does." ); return ; } if (oldPackage.parentPackage != null ) { res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, "Package " + pkg.packageName + " is child of package " + oldPackage.parentPackage + ". Child packages " + "can be updated only through the parent package." ); return ; } } } PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null ) { if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) { if (!checkUpgradeKeySetLP(ps, pkg)) { res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + pkg.packageName + " upgrade keys do not match the " + "previously installed version" ); return ; } } else { try { verifySignaturesLP(ps, pkg); } catch (PackageManagerException e) { res.setError(e.error, e.getMessage()); return ; } } oldCodePath = mSettings.mPackages.get(pkgName).codePathString; if (ps.pkg != null && ps.pkg.applicationInfo != null ) { systemApp = (ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ; } res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true ); } int N = pkg.permissions.size(); for (int i = N-1 ; i >= 0 ; i--) { PackageParser.Permission perm = pkg.permissions.get(i); BasePermission bp = mSettings.mPermissions.get(perm.info.name); if (bp != null ) { final boolean sigsOk; if (bp.sourcePackage.equals(pkg.packageName) && (bp.packageSetting instanceof PackageSetting) && (shouldCheckUpgradeKeySetLP((PackageSetting) bp.packageSetting, scanFlags))) { sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg); } else { sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures, pkg.mSignatures) == PackageManager.SIGNATURE_MATCH; } if (!sigsOk) { if (!bp.sourcePackage.equals("android" )) { res.setError(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package " + pkg.packageName + " attempting to redeclare permission " + perm.info.name + " already owned by " + bp.sourcePackage); res.origPermission = perm.info.name; res.origPackage = bp.sourcePackage; return ; } else { Slog.w(TAG, "Package " + pkg.packageName + " attempting to redeclare system permission " + perm.info.name + "; ignoring new declaration" ); pkg.permissions.remove(i); } } } } } if (systemApp) { if (onExternal) { res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION, "Cannot install updates to system apps on sdcard" ); return ; } else if (ephemeral) { res.setError(INSTALL_FAILED_EPHEMERAL_INVALID, "Cannot update a system app with an ephemeral app" ); return ; } } if (args.move != null ) { scanFlags |= SCAN_NO_DEX; scanFlags |= SCAN_MOVE; synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps == null ) { res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Missing settings for moved package " + pkgName); } pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString; pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString; } } else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) { scanFlags |= SCAN_NO_DEX; try { String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ? args.abiOverride : pkg.cpuAbiOverride); derivePackageAbi(pkg, new File(pkg.codePath), abiOverride, true ); } catch (PackageManagerException pme) { Slog.e(TAG, "Error deriving application ABI" , pme); res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI" ); return ; } synchronized (mPackages) { try { updateSharedLibrariesLPw(pkg, null ); } catch (PackageManagerException e) { Slog.e(TAG, "updateSharedLibrariesLPw failed: " + e.getMessage()); } } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt" ); mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, null , false , getCompilerFilterForReason(REASON_INSTALL), getOrCreateCompilerPackageStats(pkg)); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); BackgroundDexOptService.notifyPackageChanged(pkg.packageName); } if (!args.doRename(res.returnCode, pkg, oldCodePath)) { res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename" ); return ; } startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg); try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags, "installPackageLI" )) { if (replace) { replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user, installerPackageName, res); } else { installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES, args.user, installerPackageName, volumeUuid, res); } } synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null ) { res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true ); } final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName); PackageSetting childPs = mSettings.peekPackageLPr(childPkg.packageName); if (childPs != null ) { childRes.newUsers = childPs.queryInstalledUsers( sUserManager.getUserIds(), true ); } } } }
5.7.3.1 PackageParser.parsePackage PackageParser.parsePackage 其实我们在 PMS 启动扫描的过程中已经分析过了,这里我们重点关注其对 installFlags 的处理!
5.7.3.2 shouldCheckUpgradeKeySetLP 判断是否应该检查签名更新:
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 boolean shouldCheckUpgradeKeySetLP (PackageSetting oldPs, int scanFlags) { if (oldPs == null || (scanFlags & SCAN_INITIAL) != 0 || oldPs.sharedUser != null || !oldPs.keySetData.isUsingUpgradeKeySets()) { return false ; } KeySetManagerService ksms = mSettings.mKeySetManagerService; long [] upgradeKeySets = oldPs.keySetData.getUpgradeKeySets(); for (int i = 0 ; i < upgradeKeySets.length; i++) { if (!ksms.isIdValidKeySetId(upgradeKeySets[i])) { Slog.wtf(TAG, "Package " + (oldPs.name != null ? oldPs.name : "<null>" ) + " contains upgrade-key-set reference to unknown key-set: " + upgradeKeySets[i] + " reverting to signatures check." ); return false ; } } return true ; }
先分析到这里!
5.7.3.3 checkUpgradeKeySetLP 进行签名更新检查:1 2 3 4 5 6 7 8 9 10 11 12 private boolean checkUpgradeKeySetLP (PackageSetting oldPS, PackageParser.Package newPkg) { long [] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets(); KeySetManagerService ksms = mSettings.mKeySetManagerService; for (int i = 0 ; i < upgradeKeySets.length; i++) { Set<PublicKey> upgradeSet = ksms.getPublicKeysFromKeySetLPr(upgradeKeySets[i]); if (upgradeSet != null && newPkg.mSigningKeys.containsAll(upgradeSet)) { return true ; } } return false ; }
5.7.3.4 verifySignaturesLP 校验签名:
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 private void verifySignaturesLP (PackageSetting pkgSetting, PackageParser.Package pkg) throws PackageManagerException { if (pkgSetting.signatures.mSignatures != null ) { boolean match = compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) == PackageManager.SIGNATURE_MATCH; if (!match) { match = compareSignaturesCompat(pkgSetting.signatures, pkg) == PackageManager.SIGNATURE_MATCH; } if (!match) { match = compareSignaturesRecover(pkgSetting.signatures, pkg) == PackageManager.SIGNATURE_MATCH; } if (!match) { throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + pkg.packageName + " signatures do not match the " + "previously installed version; ignoring!" ); } } if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null ) { boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures, pkg.mSignatures) == PackageManager.SIGNATURE_MATCH; if (!match) { match = compareSignaturesCompat(pkgSetting.sharedUser.signatures, pkg) == PackageManager.SIGNATURE_MATCH; } if (!match) { match = compareSignaturesRecover(pkgSetting.sharedUser.signatures, pkg) == PackageManager.SIGNATURE_MATCH; } if (!match) { throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE, "Package " + pkg.packageName + " has no signatures that match those in shared user " + pkgSetting.sharedUser.name + "; ignoring!" ); } } }
5.7.3.5 FileInstallArgs.doRename - 重命名临时目录 doRename 重命名文件!之前我们的临时目录为 /data/app/tmpl[SessionId].tmp,这里会将其重命名为 /data/app/packageName-X!!
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 boolean doRename (int status, PackageParser.Package pkg, String oldCodePath) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); return false ; } final File targetDir = codeFile.getParentFile(); final File beforeCodeFile = codeFile; final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName); if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile); try { Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath()); } catch (ErrnoException e) { Slog.w(TAG, "Failed to rename" , e); return false ; } if (!SELinux.restoreconRecursive(afterCodeFile)) { Slog.w(TAG, "Failed to restorecon" ); return false ; } codeFile = afterCodeFile; resourceFile = afterCodeFile; pkg.setCodePath(afterCodeFile.getAbsolutePath()); pkg.setBaseCodePath(FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile, pkg.baseCodePath)); pkg.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile, pkg.splitCodePaths)); pkg.setApplicationVolumeUuid(pkg.volumeUuid); pkg.setApplicationInfoCodePath(pkg.codePath); pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); pkg.setApplicationInfoResourcePath(pkg.codePath); pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); return true ; }
流程很简单,不多说了!
5.7.3.5.1 getNextCodePath getNextCodePath 方法用于获得最终的目录!
1 2 3 4 5 6 7 8 9 10 11 private File getNextCodePath (File targetDir, String packageName) { int suffix = 1 ; File result; do { result = new File(targetDir, packageName + "-" + suffix); suffix++; } while (result.exists()); return result; }
逻辑很简单,不多说了!
5.7.3.7 freezePackageForInstall - 冻结应用 该方法用于冻结应用:
1 2 3 4 public PackageFreezer freezePackageForInstall (String packageName, int installFlags, String killReason) { return freezePackageForInstall(packageName, UserHandle.USER_ALL, installFlags, killReason); }
继续来看:1 2 3 4 5 6 7 8 9 10 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); } }
继续调用 freezePackage 方法:1 2 3 4 public PackageFreezer freezePackage (String packageName, int userId, String killReason) { return new PackageFreezer(packageName, userId, killReason); }
5.7.3.7.1 new PackageFreezer 如果不杀进程,那就只创建一个 PackageFreezer 实例,并返回,不做任何事情!
1 2 3 4 5 6 public PackageFreezer () { mPackageName = null ; mChildren = null ; mWeFroze = false ; mCloseGuard.open("close" ); }
如果要 kill app,那么会创建 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 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" ); }
这里就不多说了!!
5.7.4 FileInstallArgs.doPostInstall 清理操作,正常情况不会触发!
1 2 3 4 5 6 7 8 int doPostInstall (int status, int uid) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); } return status; }
5.7.5 new PostInstallData 又创建了一个 PostInstallData 对象,对 PackageInstalledInfo 做了再次封装:
1 2 3 4 5 6 7 8 9 static class PostInstallData { public InstallArgs args; public PackageInstalledInfo res; PostInstallData(InstallArgs _a, PackageInstalledInfo _r) { args = _a; res = _r; } }
继续来看!!
5.8 PackageHandler.doHandleMessage[POST_INSTALL] - 安装收尾 PackageHandler 会处理 POST_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 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 case POST_INSTALL: { if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1); PostInstallData data = mRunningInstalls.get(msg.arg1); final boolean didRestore = (msg.arg2 != 0 ); mRunningInstalls.delete(msg.arg1); if (data != null ) { InstallArgs args = data.args; PackageInstalledInfo parentRes = data.res; final boolean grantPermissions = (args.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0 ; final boolean killApp = (args.installFlags & PackageManager.INSTALL_DONT_KILL_APP) == 0 ; final String[] grantedPermissions = args.installGrantPermissions; handlePackagePostInstall(parentRes, grantPermissions, killApp, grantedPermissions, didRestore, args.installerPackageName, args.observer); final int childCount = (parentRes.addedChildPackages != null ) ? parentRes.addedChildPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i); handlePackagePostInstall(childRes, grantPermissions, killApp, grantedPermissions, false , args.installerPackageName, args.observer); } if (args.traceMethod != null ) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod, args.traceCookie); } } else { Slog.e(TAG, "Bogus post-install token " + msg.arg1); } Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall" , msg.arg1); } break ;
继续处理!
5.8.1 PackageManagerS.handlePackagePostInstall 处理安装收尾工作:
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 private void handlePackagePostInstall (PackageInstalledInfo res, boolean grantPermissions, boolean killApp, String[] grantedPermissions, boolean launchedForRestore, String installerPackage, IPackageInstallObserver2 installObserver) { if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { if (res.removedInfo != null ) { res.removedInfo.sendPackageRemovedBroadcasts(killApp); } if (grantPermissions && res.pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) { grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions); } final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null ; if (res.pkg.parentPackage != null ) { synchronized (mPackages) { grantRuntimePermissionsGrantedToDisabledPrivSysPackageParentLPw(res.pkg); } } synchronized (mPackages) { mEphemeralApplicationRegistry.onPackageInstalledLPw(res.pkg); } final String packageName = res.pkg.applicationInfo.packageName; Bundle extras = new Bundle(1 ); extras.putInt(Intent.EXTRA_UID, res.uid); int [] firstUsers = EMPTY_INT_ARRAY; int [] updateUsers = EMPTY_INT_ARRAY; if (res.origUsers == null || res.origUsers.length == 0 ) { firstUsers = res.newUsers; } else { for (int newUser : res.newUsers) { boolean isNew = true ; for (int origUser : res.origUsers) { if (origUser == newUser) { isNew = false ; break ; } } if (isNew) { firstUsers = ArrayUtils.appendInt(firstUsers, newUser); } else { updateUsers = ArrayUtils.appendInt(updateUsers, newUser); } } } if (!isEphemeral(res.pkg)) { mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath); sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 , null , null , firstUsers); if (update) { extras.putBoolean(Intent.EXTRA_REPLACING, true ); } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 , null , null , updateUsers); if (update) { sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, 0 , null , null , updateUsers); sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null , null , 0 , packageName , null , updateUsers); } else if (launchedForRestore && !isSystemApp(res.pkg)) { if (DEBUG_BACKUP) { Slog.i(TAG, "Post-restore of " + packageName + " sending FIRST_LAUNCH in " + Arrays.toString(firstUsers)); } sendFirstLaunchBroadcast(packageName, installerPackage, firstUsers); } if (res.pkg.isForwardLocked() || isExternal(res.pkg)) { if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + res.pkg + " is ASEC-hosted -> AVAILABLE" ); } final int [] uidArray = new int []{res.pkg.applicationInfo.uid}; ArrayList<String> pkgList = new ArrayList<>(1 ); pkgList.add(packageName); sendResourcesChangedBroadcast(true , true , pkgList, uidArray, null ); } } if (firstUsers != null && firstUsers.length > 0 ) { synchronized (mPackages) { for (int userId : firstUsers) { if (packageIsBrowser(packageName, userId)) { mSettings.setDefaultBrowserPackageNameLPw(null , userId); } mSettings.applyPendingPermissionGrantsLPw(packageName, userId); } } } EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED, getUnknownSourcesSettings()); Runtime.getRuntime().gc(); if (res.removedInfo != null && res.removedInfo.args != null ) { synchronized (mInstallLock) { res.removedInfo.args.doPostDeleteLI(true ); } } } if (installObserver != null ) { try { Bundle extras = extrasForInstallResult(res); installObserver.onPackageInstalled(res.name, res.returnCode, res.returnMsg, extras); } catch (RemoteException e) { Slog.i(TAG, "Observer no longer exists." ); } } }
我们看到,这里涉及到了几个重要的广播:
Intent.ACTION_PACKAGE_ADDED :当有应用程序第一次安装时,会发送该广播给对应的 firstUsers!
携带数据:Intent.EXTRA_UID,值为 apk uid;
Intent.ACTION_PACKAGE_REPLACED :当有应用程序被覆盖安装时,会发送该广播给对应的 updateUsers!
携带数据:Intent.EXTRA_UID,
携带数据:Intent.EXTRA_REPLACING,置为 true;
Intent.ACTION_MY_PACKAGE_REPLACED :当有应用程序被覆盖安装时,会发送该广播给对应的 updateUsers 下被更新的 pkg!
携带数据:packageName,被更新的应用包;
5.8.1.1 FileInstallArgs.doPostDeleteLI - 删除被更新的旧 apk 继续来看:
1 2 3 4 5 boolean doPostDeleteLI (boolean delete) { cleanUpResourcesLI(); return true ; }
继续分析:
5.8.1.2 FileInstallArgs.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); }
这里就不再过多分析!
5.8.2 IPackageInstallObserver2.onPackageInstalled 这里的 installObserver 是我们在 4.3 PackageInstallerSession.commitLocked 中创建的另一个 Observer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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); } };
5.8.2.1 PackageInstallerSession.destroyInternal 关闭文件桥,删除文件拷贝:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void destroyInternal () { synchronized (mLock) { mSealed = true ; mDestroyed = true ; for (FileBridge bridge : mBridges) { bridge.forceClose(); } } if (stageDir != null ) { try { mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath()); } catch (InstallerException ignored) { } } if (stageCid != null ) { PackageHelper.destroySdDir(stageCid); } }
5.8.2.2 PackageInstallerSession.dispatchSessionFinished 处理回调,通知监听者!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void dispatchSessionFinished (int returnCode, String msg, Bundle extras) { mFinalStatus = returnCode; mFinalMessage = msg; if (mRemoteObserver != null ) { try { mRemoteObserver.onPackageInstalled(mPackageName, returnCode, msg, extras); } catch (RemoteException ignored) { } } final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED); mCallback.onSessionFinished(this , success); }
在前面 4.1 commit 事务的时候,我们创建了一个 PackageInstallObserverAdapter,并将其保存到了 PackageInstallerSession.mRemoteObserver 中,这里首先会触发 mRemoteObserver 的回调!
在 3.1.4.1 new InternalCallback 的时候,我们在创建 PackageInstallerSession 时,传入了一个回调对象 InternalCallback:
1 private final InternalCallback mInternalCallback = new InternalCallback();
InternalCallback 类定义在 PackageInstallerService 中,该对象的引用会被保存到 PackageInstallerSession.mCallback 变量中!
5.8.2.2.2 InternalCallback.onSessionFinished 这里我们重点关于 onSessionFinished 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public void onSessionFinished (final PackageInstallerSession session, boolean success) { mCallbacks.notifySessionFinished(session.sessionId, session.userId, success); mInstallHandler.post(new Runnable() { @Override public void run () { synchronized (mSessions) { mSessions.remove(session.sessionId); mHistoricalSessions.put(session.sessionId, session); final File appIconFile = buildAppIconFile(session.sessionId); if (appIconFile.exists()) { appIconFile.delete(); } writeSessionsLocked(); } } }); }
我们看到,在 InternalCallback 中又回调了另外一个 Callback mCallbacks,它也是 PackageInstallerService 的内部类:
5.8.2.2.2.1 Callback.notifySessionFinished 前面我们分析过,Callback 本质上就是一个 Handler,这里就是向其所在的线程发送消息:1 2 3 public void notifySessionFinished (int sessionId, int userId, boolean success) { obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget(); }
在 3.1.4.2 Callbacks.notifySessionXXXX 中,我们分析过,最终其实是很将安装的结果分发给了注册在 Callback 中的所有远程回调:
1 2 private final RemoteCallbackList<IPackageInstallerCallback> mCallbacks = new RemoteCallbackList<>();
这里就不多说了!
6 PackageManagerS.replacePackageLIF - 覆盖安装 6.1 参数分析 这里我们来回顾下传入的参数:final int policyFlags 就是我们之前的解析参数 parseFlags
1 2 3 4 5 6 7 final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0 ) | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0 ) | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0 ) | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0 );
同时,对于扫描标志位 scanFlags,会做如下处理:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;if (args.move != null ) { scanFlags |= SCAN_INITIAL; } if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0 ) { scanFlags |= SCAN_DONT_KILL_APP; } ... ... if (args.move != null ) { scanFlags |= SCAN_NO_DEX; scanFlags |= SCAN_MOVE; ... ... ... } else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) { scanFlags |= SCAN_NO_DEX; ... ... ... }
上面,我们省略掉了不重要的代码段!
6.2 方法分析 下面继续分析核心方法:
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 private void replacePackageLIF (PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, String installerPackageName, PackageInstalledInfo res) { final boolean isEphemeral = (policyFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0 ; final PackageParser.Package oldPackage; final String pkgName = pkg.packageName; final int [] allUsers; final int [] installedUsers; synchronized (mPackages) { oldPackage = mPackages.get(pkgName); if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage); final boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion == android.os.Build.VERSION_CODES.CUR_DEVELOPMENT; final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion == android.os.Build.VERSION_CODES.CUR_DEVELOPMENT; if (oldTargetsPreRelease && !newTargetsPreRelease && ((policyFlags & PackageParser.PARSE_FORCE_SDK) == 0 )) { Slog.w(TAG, "Can't install package targeting released sdk" ); res.setReturnCode(PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE); return ; } final boolean oldIsEphemeral = oldPackage.applicationInfo.isEphemeralApp(); if (isEphemeral && !oldIsEphemeral) { Slog.w(TAG, "Can't replace app with ephemeral: " + pkgName); res.setReturnCode(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID); return ; } final PackageSetting ps = mSettings.mPackages.get(pkgName); if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) { if (!checkUpgradeKeySetLP(ps, pkg)) { res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "New package not signed by keys specified by upgrade-keysets: " + pkgName); return ; } } else { if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "New package has a different signature: " + pkgName); return ; } } if (oldPackage.restrictUpdateHash != null && oldPackage.isSystemApp()) { byte [] digestBytes = null ; try { final MessageDigest digest = MessageDigest.getInstance("SHA-512" ); updateDigest(digest, new File(pkg.baseCodePath)); if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { for (String path : pkg.splitCodePaths) { updateDigest(digest, new File(path)); } } digestBytes = digest.digest(); } catch (NoSuchAlgorithmException | IOException e) { res.setError(INSTALL_FAILED_INVALID_APK, "Could not compute hash: " + pkgName); return ; } if (!Arrays.equals(oldPackage.restrictUpdateHash, digestBytes)) { res.setError(INSTALL_FAILED_INVALID_APK, "New package fails restrict-update check: " + pkgName); return ; } pkg.restrictUpdateHash = oldPackage.restrictUpdateHash; } String invalidPackageName = getParentOrChildPackageChangedSharedUser(oldPackage, pkg); if (invalidPackageName != null ) { res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE, "Package " + invalidPackageName + " tried to change user " + oldPackage.mSharedUserId); return ; } allUsers = sUserManager.getUserIds(); installedUsers = ps.queryInstalledUsers(allUsers, true ); } res.removedInfo = new PackageRemovedInfo(); res.removedInfo.uid = oldPackage.applicationInfo.uid; res.removedInfo.removedPackage = oldPackage.packageName; res.removedInfo.isUpdate = true ; res.removedInfo.origUsers = installedUsers; final int childCount = (oldPackage.childPackages != null ) ? oldPackage.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { boolean childPackageUpdated = false ; PackageParser.Package childPkg = oldPackage.childPackages.get(i); if (res.addedChildPackages != null ) { PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName); if (childRes != null ) { childRes.removedInfo.uid = childPkg.applicationInfo.uid; childRes.removedInfo.removedPackage = childPkg.packageName; childRes.removedInfo.isUpdate = true ; childPackageUpdated = true ; } } if (!childPackageUpdated) { PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(); childRemovedRes.removedPackage = childPkg.packageName; childRemovedRes.isUpdate = false ; childRemovedRes.dataRemoved = true ; synchronized (mPackages) { PackageSetting childPs = mSettings.peekPackageLPr(childPkg.packageName); if (childPs != null ) { childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers, true ); } } if (res.removedInfo.removedChildPackages == null ) { res.removedInfo.removedChildPackages = new ArrayMap<>(); } res.removedInfo.removedChildPackages.put(childPkg.packageName, childRemovedRes); } } boolean sysPkg = (isSystemApp(oldPackage)); if (sysPkg) { final boolean privileged = (oldPackage.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ; final int systemPolicyFlags = policyFlags | PackageParser.PARSE_IS_SYSTEM | (privileged ? PackageParser.PARSE_IS_PRIVILEGED : 0 ); replaceSystemPackageLIF(oldPackage, pkg, systemPolicyFlags, scanFlags, user, allUsers, installerPackageName, res); } else { replaceNonSystemPackageLIF(oldPackage, pkg, policyFlags, scanFlags, user, allUsers, installerPackageName, res); } }
对于判断是否是系统应用,调用了如下的接口:
1 2 3 private static boolean isSystemApp (PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ; }
6.2.1 replaceSystemPackageLIF - 覆盖安装系统应用 这里我们来回顾下传入的参数:final int policyFlags 就是我们之前的解析参数 parseFlags
1 2 3 4 5 6 7 8 9 10 11 12 final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0 ) | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0 ) | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0 ) | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0 ); final int systemPolicyFlags = policyFlags | PackageParser.PARSE_IS_SYSTEM | (privileged ? PackageParser.PARSE_IS_PRIVILEGED : 0 );
同时,对于扫描标志位 scanFlags,和上面保持一致,下面我们来分析下更新 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 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 private void replaceSystemPackageLIF (PackageParser.Package deletedPackage, PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, int [] allUsers, String installerPackageName, PackageInstalledInfo res) { if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg + ", old=" + deletedPackage); final boolean disabledSystem; removePackageLI(deletedPackage, true ); synchronized (mPackages) { disabledSystem = disableSystemPackageLPw(deletedPackage, pkg); } if (!disabledSystem) { res.removedInfo.args = createInstallArgsForExisting(0 , deletedPackage.applicationInfo.getCodePath(), deletedPackage.applicationInfo.getResourcePath(), getAppDexInstructionSets(deletedPackage.applicationInfo)); } else { res.removedInfo.args = null ; } clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); clearAppProfilesLIF(deletedPackage, UserHandle.USER_ALL); res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); PackageParser.Package newPackage = null ; try { newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, 0 , user); PackageSetting deletedPkgSetting = (PackageSetting) deletedPackage.mExtras; setInstallAndUpdateTime(newPackage, deletedPkgSetting.firstInstallTime, System.currentTimeMillis()); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { final int deletedChildCount = (deletedPackage.childPackages != null ) ? deletedPackage.childPackages.size() : 0 ; final int newChildCount = (newPackage.childPackages != null ) ? newPackage.childPackages.size() : 0 ; for (int i = 0 ; i < deletedChildCount; i++) { PackageParser.Package deletedChildPkg = deletedPackage.childPackages.get(i); boolean childPackageDeleted = true ; for (int j = 0 ; j < newChildCount; j++) { PackageParser.Package newChildPkg = newPackage.childPackages.get(j); if (deletedChildPkg.packageName.equals(newChildPkg.packageName)) { childPackageDeleted = false ; break ; } } if (childPackageDeleted) { PackageSetting ps = mSettings.getDisabledSystemPkgLPr( deletedChildPkg.packageName); if (ps != null && res.removedInfo.removedChildPackages != null ) { PackageRemovedInfo removedChildRes = res.removedInfo .removedChildPackages.get(deletedChildPkg.packageName); removePackageDataLIF(ps, allUsers, removedChildRes, 0 , false ); removedChildRes.removedForAllUsers = mPackages.get(ps.name) == null ; } } } updateSettingsLI(newPackage, installerPackageName, allUsers, res, user); prepareAppDataAfterInstallLIF(newPackage); } } catch (PackageManagerException e) { res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR); res.setError("Package couldn't be installed in " + pkg.codePath, e); } if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { if (newPackage != null ) { removeInstalledPackageLI(newPackage, true ); } try { scanPackageTracedLI(deletedPackage, policyFlags, SCAN_UPDATE_SIGNATURE, 0 , user); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to restore original package: " + e.getMessage()); } synchronized (mPackages) { if (disabledSystem) { enableSystemPackageLPw(deletedPackage); } setInstallerPackageNameLPw(deletedPackage, installerPackageName); updatePermissionsLPw(deletedPackage, UPDATE_PERMISSIONS_ALL); mSettings.writeLPr(); } Slog.i(TAG, "Successfully restored package : " + deletedPackage.packageName + " after failed upgrade" ); } }
这里就不多说了!!
6.2.1.1 removePackageLI 移除旧的 apk 的数据信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void removePackageLI (PackageParser.Package pkg, boolean chatty) { PackageSetting ps = (PackageSetting) pkg.mExtras; if (ps != null ) { removePackageLI(ps, chatty); } final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); ps = (PackageSetting) childPkg.mExtras; if (ps != null ) { removePackageLI(ps, chatty); } } }
调用了另外一个 removePackageLI 方法!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 disableSystemPackageLPw disable 掉系统应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private boolean disableSystemPackageLPw (PackageParser.Package oldPkg, PackageParser.Package newPkg) { boolean disabled = mSettings.disableSystemPackageLPw(oldPkg.packageName, true ); final int childCount = (oldPkg.childPackages != null ) ? oldPkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPkg = oldPkg.childPackages.get(i); final boolean replace = newPkg.hasChildPackage(childPkg.packageName); disabled |= mSettings.disableSystemPackageLPw(childPkg.packageName, replace); } return disabled; }
这里调用了 Settings 的 disableSystemPackageLPw 方法!
6.2.1.2.1 Settings.disableSystemPackageLPw 我们继续分析:
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 boolean disableSystemPackageLPw (String name, boolean replaced) { final PackageSetting p = mPackages.get(name); if (p == null ) { Log.w(PackageManagerService.TAG, "Package " + name + " is not an installed package" ); return false ; } final PackageSetting dp = mDisabledSysPackages.get(name); if (dp == null && p.pkg != null && p.pkg.isSystemApp() && !p.pkg.isUpdatedSystemApp()) { if ((p.pkg != null ) && (p.pkg.applicationInfo != null )) { p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } mDisabledSysPackages.put(name, p); if (replaced) { PackageSetting newp = new PackageSetting(p); replacePackageLPw(name, newp); } return true ; } return false ; }
可以看到,对于系统应用来说,只有第一次覆盖更新时,会 disable 掉 sys 下的那个 app;如果多次覆盖安装,后续的不会再 disable!
下面是替换的具体操作!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private void replacePackageLPw (String name, PackageSetting newp) { final PackageSetting p = mPackages.get(name); if (p != null ) { if (p.sharedUser != null ) { p.sharedUser.removePackage(p); p.sharedUser.addPackage(newp); } else { replaceUserIdLPw(p.appId, newp); } } mPackages.put(name, newp); }
旧的数据,此时是在 mDisabledSysPackages 中!
6.2.1.3 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 25 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.1.4 clearAppDataLIF 清楚 app 的数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 private void clearAppDataLIF (PackageParser.Package pkg, int userId, int flags) { if (pkg == null ) { Slog.wtf(TAG, "Package was null!" , new Throwable()); return ; } clearAppDataLeafLIF(pkg, userId, flags); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); } }
继续看:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private void clearAppDataLeafLIF (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.clearAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags, ceDataInode); } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); } } }
6.2.1.5 clearAppProfilesLIF 清楚 app 的 profiles 数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void clearAppProfilesLIF (PackageParser.Package pkg, int userId) { if (pkg == null ) { Slog.wtf(TAG, "Package was null!" , new Throwable()); return ; } clearAppProfilesLeafLIF(pkg); destroyAppReferenceProfileLeafLIF(pkg, userId, false ); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { clearAppProfilesLeafLIF(pkg.childPackages.get(i)); } }
6.2.1.5.1 clearAppProfilesLeafLIF 最终调用了这个方法,清楚 profile 数据:1 2 3 4 5 6 7 private void clearAppProfilesLeafLIF (PackageParser.Package pkg) { try { mInstaller.clearAppProfiles(pkg.packageName); } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); } }
6.2.1.6 removeInstalledPackageLI 移除被扫描到的新的 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 void removeInstalledPackageLI (PackageParser.Package pkg, boolean chatty) { if (DEBUG_INSTALL) { if (chatty) Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName); } synchronized (mPackages) { mPackages.remove(pkg.applicationInfo.packageName); cleanPackageDataStructuresLILPw(pkg, chatty); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); mPackages.remove(childPkg.applicationInfo.packageName); cleanPackageDataStructuresLILPw(childPkg, chatty); } } }
6.2.1.7 enableSystemPackageLPw 恢复系统应用
1 2 3 4 5 6 7 8 9 10 11 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.2.1.7.1 Settings.enableSystemPackageLPw 最终会调用 Settings 的 enableSystemPackageLPw 方法 enable package:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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; }
关于 addPackageLPw 的逻辑这里就不在分析了!
6.2.2 replaceNonSystemPackageLIF - 覆盖安装三方应用 -> 接入 8 关于 replaceNonSystemPackageLIF 的逻辑,由于 markdown 不支持 6 级以上的标题,所以移动到第 8 节,单独分析!!
7 PackageManagerS.installNewPackageLIF - 全新安装 7.1 参数分析 这里我们来回顾下传入的参数:final int policyFlags 就是我们之前的解析参数 parseFlags
1 2 3 4 5 6 7 final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0 ) | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0 ) | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0 ) | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0 );
同时,对于扫描标志位 scanFlags,会做如下处理:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;if (args.move != null ) { scanFlags |= SCAN_INITIAL; } if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0 ) { scanFlags |= SCAN_DONT_KILL_APP; } ... ... ... if (args.move != null ) { scanFlags |= SCAN_NO_DEX; scanFlags |= SCAN_MOVE; ... ... ... } else if (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) { scanFlags |= SCAN_NO_DEX; ... ... ... }
上面我们省略掉了不重要的代码段!
7.2 方法解析 下面继续分析核心方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 private void installNewPackageLIF (PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage" ); String pkgName = pkg.packageName; if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg); synchronized (mPackages) { if (mSettings.mRenamedPackages.containsKey(pkgName)) { res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName + " without first uninstalling package running as " + mSettings.mRenamedPackages.get(pkgName)); return ; } if (mPackages.containsKey(pkgName)) { res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName + " without first uninstalling." ); return ; } } try { PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, System.currentTimeMillis(), user); updateSettingsLI(newPackage, installerPackageName, null , res, user); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { prepareAppDataAfterInstallLIF(newPackage); } else { deletePackageLIF(pkgName, UserHandle.ALL, false , null , PackageManager.DELETE_KEEP_DATA, res.removedInfo, true , null ); } } catch (PackageManagerException e) { res.setError("Package couldn't be installed in " + pkg.codePath, e); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }
继续分析:
7.2.1 updateSettingsLI 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private void updateSettingsLI (PackageParser.Package newPackage, String installerPackageName, int [] allUsers, PackageInstalledInfo res, UserHandle user) { updateSettingsInternalLI(newPackage, installerPackageName, allUsers, res.origUsers, res, user); final int childCount = (newPackage.childPackages != null ) ? newPackage.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { PackageParser.Package childPackage = newPackage.childPackages.get(i); PackageInstalledInfo childRes = res.addedChildPackages.get(childPackage.packageName); updateSettingsInternalLI(childPackage, installerPackageName, allUsers, childRes.origUsers, childRes, user); } }
继续来看:
7.2.1.1 updateSettingsInternalLI 此时,apk 已经扫描了,在扫描的最后阶段,也会创建对应的 PackageSettings 对象,这里会根据安装结果,更新数据!
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 void updateSettingsInternalLI (PackageParser.Package newPackage, String installerPackageName, int [] allUsers, int [] installedForUsers, PackageInstalledInfo res, UserHandle user) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings" ); String pkgName = newPackage.packageName; synchronized (mPackages) { mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings" ); mSettings.writeLPr(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.codePath); synchronized (mPackages) { updatePermissionsLPw(newPackage.packageName, newPackage, UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0 )); PackageSetting ps = mSettings.mPackages.get(pkgName); final int userId = user.getIdentifier(); if (ps != null ) { if (isSystemApp(newPackage)) { if (DEBUG_INSTALL) { Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName); } if (res.origUsers != null ) { for (int origUserId : res.origUsers) { if (userId == UserHandle.USER_ALL || userId == origUserId) { ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, origUserId, installerPackageName); } } } if (allUsers != null && installedForUsers != null ) { for (int currentUserId : allUsers) { final boolean installed = ArrayUtils.contains( installedForUsers, currentUserId); if (DEBUG_INSTALL) { Slog.d(TAG, " user " + currentUserId + " => " + installed); } ps.setInstalled(installed, currentUserId); } } } if (userId != UserHandle.USER_ALL) { ps.setInstalled(true , userId); ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName); } } res.name = pkgName; res.uid = newPackage.applicationInfo.uid; res.pkg = newPackage; mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE); mSettings.setInstallerPackageName(pkgName, installerPackageName); res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings" ); mSettings.writeLPr(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }
7.2.2 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 26 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); } } }
暂时分析到这里!
7.2.2.1 prepareAppDataLIF 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); } }
7.2.2.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 54 55 56 57 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); }
8 PackageManagerS.replaceNonSystemPackageLIF - 接 6.2.2 这里我们分析下覆盖安装三方应用的流程,对于扫描标志位 scanFlags,和上面保持一致:
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 private void replaceNonSystemPackageLIF (PackageParser.Package deletedPackage, PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, int [] allUsers, String installerPackageName, PackageInstalledInfo res) { if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old=" + deletedPackage); String pkgName = deletedPackage.packageName; boolean deletedPkg = true ; boolean addedPkg = false ; boolean updatedSettings = false ; final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0 ; final int deleteFlags = PackageManager.DELETE_KEEP_DATA | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP); final long origUpdateTime = (pkg.mExtras != null ) ? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0 ; if (!deletePackageLIF(pkgName, null , true , allUsers, deleteFlags, res.removedInfo, true , pkg)) { res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI" ); deletedPkg = false ; } else { if (deletedPackage.isForwardLocked() || isExternal(deletedPackage)) { if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + deletedPackage + " is ASEC-hosted -> UNAVAILABLE" ); } final int [] uidArray = new int [] { deletedPackage.applicationInfo.uid }; final ArrayList<String> pkgList = new ArrayList<String>(1 ); pkgList.add(deletedPackage.applicationInfo.packageName); sendResourcesChangedBroadcast(false , true , pkgList, uidArray, null ); } clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); clearAppProfilesLIF(deletedPackage, UserHandle.USER_ALL); try { final PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user); updateSettingsLI(newPackage, installerPackageName, allUsers, res, user); PackageSetting ps = mSettings.mPackages.get(pkgName); if (!killApp) { if (ps.oldCodePaths == null ) { ps.oldCodePaths = new ArraySet<>(); } Collections.addAll(ps.oldCodePaths, deletedPackage.baseCodePath); if (deletedPackage.splitCodePaths != null ) { Collections.addAll(ps.oldCodePaths, deletedPackage.splitCodePaths); } } else { ps.oldCodePaths = null ; } if (ps.childPackageNames != null ) { for (int i = ps.childPackageNames.size() - 1 ; i >= 0 ; --i) { final String childPkgName = ps.childPackageNames.get(i); final PackageSetting childPs = mSettings.mPackages.get(childPkgName); childPs.oldCodePaths = ps.oldCodePaths; } } prepareAppDataAfterInstallLIF(newPackage); addedPkg = true ; } catch (PackageManagerException e) { res.setError("Package couldn't be installed in " + pkg.codePath, e); } } if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, rolling pack: " + pkgName); if (addedPkg) { deletePackageLIF(pkgName, null , true , allUsers, deleteFlags, res.removedInfo, true , null ); } if (deletedPkg) { if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage); File restoreFile = new File(deletedPackage.codePath); boolean oldExternal = isExternal(deletedPackage); int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | (deletedPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0 ) | (oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0 ); int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME; try { scanPackageTracedLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime, null ); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: " + e.getMessage()); return ; } synchronized (mPackages) { setInstallerPackageNameLPw(deletedPackage, installerPackageName); updatePermissionsLPw(deletedPackage, UPDATE_PERMISSIONS_ALL); mSettings.writeLPr(); } Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade" ); } } else { synchronized (mPackages) { PackageSetting ps = mSettings.peekPackageLPr(pkg.packageName); if (ps != null ) { res.removedInfo.removedForAllUsers = mPackages.get(ps.name) == null ; if (res.removedInfo.removedChildPackages != null ) { final int childCount = res.removedInfo.removedChildPackages.size(); for (int i = childCount - 1 ; i >= 0 ; i--) { String childPackageName = res.removedInfo.removedChildPackages.keyAt(i); if (res.addedChildPackages.containsKey(childPackageName)) { res.removedInfo.removedChildPackages.removeAt(i); } else { PackageRemovedInfo childInfo = res.removedInfo .removedChildPackages.valueAt(i); childInfo.removedForAllUsers = mPackages.get( childInfo.removedPackage) == null ; } } } } } } }
不多说了!
8.1 deletePackageLIF 删除 apk,参数 PackageParser.Package replacingPackage 表示用于 replace 的 package:
deletePackageLIF 中的逻辑很多涉及到了 delete package 的逻辑,和 install package 并没有太大关系,我们在后面的 delete 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 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 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; }
先看到这里!
8.1.1 clearPackageStateForUserLIF 清楚指定 user 下的应用数据,这里涉及到的清理操作很多,由于篇幅,这里先不细讲,等到卸载应用时在深入分析!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 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 ; }
关于以下的内容,会在卸载 app 和权限相关文章中分析,这里由于篇幅原因(markdown 只支持 6 级标题),就先不深入分析了!
1 2 3 4 5 6 7 8 destroyAppProfilesLIF(pkg, userId); removeKeystoreDataIfNeeded(nextUserId, ps.appId); clearPackagePreferredActivitiesLPw(); resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, nextUserId);
这里就不再多说了!!
8.1.1.1 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 方法:
8.1.1.1.1 PackageSetting.getCeDataInode 1 2 3 long getCeDataInode (int userId) { return readUserState(userId).ceDataInode; }
该方法返回的是 PackageUserState.ceDataInode 的值!
8.1.1.3 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); } }
8.1.1.3.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 ;
8.1.1.3.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) { } } }
这里的逻辑就不多说了!
8.1.2 markPackageUninstalledForUserLPw 更新每个用户下的 package 的用户状态:
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 ); } }
8.1.3 deleteSystemPackageLIF 关于 flags 的设置:
1 2 3 final int deleteFlags = PackageManager.DELETE_KEEP_DATA | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
删除 system 更新 apk,PackageRemovedInfo outInfo 用于封装移除的相关信息!
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 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 ; }
这里就不在多说了!
8.1.4 deleteInstalledPackageLIF 关于 flags 的设置:
1 2 3 final int deleteFlags = PackageManager.DELETE_KEEP_DATA | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
删除 data 分区的 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 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 ; }
不多说了!
8.1.4.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 114 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); } }
不多说了!!
8.1.4.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); } } }
这个就不多说了!!