赞
踩
通过adb install命令可以将apk安装到Android系统(注意:特定类型的apk,比如persist类型是无法通过adb安装的)
下述命令中adb解析install命令,并调用Android PackageManagerService进行apk安装。
# -r : replace existing application
# -t : allow test packages\n"
# -d : allow version code downgrade (debuggable packages only)
adb install -r -t -d linduo_test.apk
基于Android12,分析从adb install到 PakcageManagerService安装apk的流程。
Android中adb的源码被放在 “packages/modules/adb”这个仓库中,这个仓库编译后的主要成果物是adbd和**adb。**adbd是a服务端进程,adb是提供的客户端工具。adb和adbd两者间,通过socket完成相互间的通信。
# packages/modules/adb/Android.bp # adbd,在Android系统中运行 cc_binary { name: "adbd", defaults: ["adbd_defaults", "host_adbd_supported", "libadbd_binary_dependencies"], recovery_available: true, apex_available: ["com.android.adbd"], srcs: [ "daemon/main.cpp", ], # 省略... } # adb,提供给Host端(就是主机PC) cc_binary_host { name: "adb", stl: "libc++_static", defaults: ["adb_defaults"], srcs: [ "client/adb_client.cpp", "client/bugreport.cpp", "client/commandline.cpp", "client/file_sync_client.cpp", "client/main.cpp", "client/console.cpp", "client/adb_install.cpp", "client/line_printer.cpp", "client/fastdeploy.cpp", "client/fastdeploycallbacks.cpp", "client/incremental.cpp", "client/incremental_server.cpp", "client/incremental_utils.cpp", "shell_service_protocol.cpp", ], # 省略... }
这里关注adb install命令对应的源码实现,adb这个bin程序对应的main函数定义在“packages/modules/adb/client/main.cpp”,main函数中调用adb_trace_init进行Trace(记录运行Log)的初始化,然后调用adb_commandline解析adb命令参数。
int main(int argc, char* argv[], char* envp[]) {
__adb_argv = const_cast<const char**>(argv);
__adb_envp = const_cast<const char**>(envp);
adb_trace_init(argv);
// 这里忽略了第一个入参(程序名自己)
return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
}
adb_commandline函数在"packages/modules/adb/client/commandline.cpp"中实现,在这个函数中解析adb命令的参数。如果是adb install命令,会调用install_app函数进行APK安装的相关流程。
int adb_commandline(int argc, const char** argv) { // 省略... // 解析各个参数 while (argc > 0) { // 解析第一个参数。就是adb命令后第一个参数 if (!strcmp(argv[0], "server")) { // 省略了很多代码... } else { // adb install 的情况下走这里,跳出循环 /* out of recognized modifiers and flags */ break; } argc--; argv++; } // 省略... /* adb_connect() commands */ if (!strcmp(argv[0], "devices")) { // 省略了很多代码(对各个命令的判断) } else if (!strcmp(argv[0], "install")) { // 判断参数为install,执行app安装相关函数 if (argc < 2) error_exit("install requires an argument"); return install_app(argc, argv); } else if (!strcmp(argv[0], "install-multiple")) { if (argc < 2) error_exit("install-multiple requires an argument"); return install_multiple_app(argc, argv); } else if (!strcmp(argv[0], "install-multi-package")) { if (argc < 2) error_exit("install-multi-package requires an argument"); return install_multi_package(argc, argv); } else if (!strcmp(argv[0], "uninstall")) { if (argc < 2) error_exit("uninstall requires an argument"); return uninstall_app(argc, argv); } else if (!strcmp(argv[0], "sync")) { // 省略... } // 省略... // 如果输入了错误的参数,会报下面的错误,并结束此次adb命令的执行 error_exit("unknown command %s", argv[0]); __builtin_unreachable(); }
install_app函数在“packages/modules/adb/client/adb_install.cpp”中定义。该函数先判断APK的安装模式是
INSTALL_PUSH/INSTALL_STREAM/INSTALL_INCREMENTAL中哪一种。默认情况下是INSTALL_PUSH模式,然后调用install_app_legacy函数进行APK安装。
int install_app(int argc, const char** argv) { InstallMode install_mode = INSTALL_DEFAULT; auto incremental_request = CmdlineOption::None; bool incremental_wait = false; bool use_fastdeploy = false; FastDeploy_AgentUpdateStrategy agent_update_strategy = FastDeploy_AgentUpdateDifferentVersion; // 进行安装默认的判断,通过parse_install_mode/parse_fast_deploy_mode/calculate_install_mode实现 // 具体实现方式请自行查看源码,这里就不关注了 auto unused_argv = parse_install_mode({argv, argv + argc}, &install_mode, &incremental_request, &incremental_wait); auto passthrough_argv = parse_fast_deploy_mode(std::move(unused_argv), &use_fastdeploy, &agent_update_strategy); auto [primary_mode, fallback_mode] = calculate_install_mode(install_mode, use_fastdeploy, incremental_request); // 省略... // adb install默认使用INSTALL_PUSH方式安装 auto run_install_mode = [&](InstallMode install_mode, bool silent) { switch (install_mode) { case INSTALL_PUSH: return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(), use_fastdeploy); case INSTALL_STREAM: return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(), use_fastdeploy); case INSTALL_INCREMENTAL: return install_app_incremental(passthrough_argv.size(), passthrough_argv.data(), incremental_wait, silent); case INSTALL_DEFAULT: default: error_exit("invalid install mode"); } }; // 如果安装失败,会使用fallback mode再次安装。默认情况下,fallback mode是空(不进行安装) auto res = run_install_mode(primary_mode, fallback_mode.has_value()); if (res && fallback_mode.value_or(primary_mode) != primary_mode) { res = run_install_mode(*fallback_mode, false); } return res; }
install_app_legacy函数定义在"packages/modules/adb/client/adb_install.cpp"中。函数执行时,会在终端输出"Performing Push Install"提示使用者。函数中判断adb install命令是否以.apk字符结束,并将apk文件push到/data/local/tmp/目录下。然后调用pm_command函数安装/data/local/tmp/目录下的apk文件。最后将/data/local/tmp/下面的apk文件删除。
static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy) { printf("Performing Push Install\n"); // 这里判断 adb install命令是否以 .apk结尾。如果没有就认为没有提供待安装apk // Find last APK argument. // All other arguments passed through verbatim. int last_apk = -1; for (int i = argc - 1; i >= 0; i--) { if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) { error_exit("APEX packages are only compatible with Streamed Install"); } if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) { last_apk = i; break; } } // 如果在adb install的命令最后字符 不是.apk的形式,报错。 if (last_apk == -1) error_exit("need APK file on command line"); // 创建临时目录 /data/local/tmp/xxx.apk,存放待安装的apk int result = -1; std::vector<const char*> apk_file = {argv[last_apk]}; std::string apk_dest = "/data/local/tmp/" + android::base::Basename(argv[last_apk]); // 注意,这里将adb install 中apk文件的路径,换成了 /data/local/tmp/xxx.apk argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */ // 如果使用快速部署(默认为false) if (use_fastdeploy) { // 省略 ... } // 将Apk push到/data/local/tmp/目录下 if (do_sync_push(apk_file, apk_dest.c_str(), false, CompressionType::Any, false)) { // 执行安装 result = pm_command(argc, argv); // 安装完成后,删除临时目录/data/local/tmp/下的apk文件。 delete_device_file(apk_dest); } return result; }
pm_command函数,顾名思义给执行pm(PackageManager)相关的命令。所以在函数中,为字符串拼接了 "pm"字符(aosp提供的pm命令)
// packages/modules/adb/client/adb_install.cpp static int pm_command(int argc, const char** argv) { std::string cmd = "pm"; while (argc-- > 0) { cmd += " " + escape_arg(*argv++); } return send_shell_command(cmd); } // packages/modules/adb/client/commandline.cpp int send_shell_command(const std::string& command, bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) { unique_fd fd; bool use_shell_protocol = false; while (true) { bool attempt_connection = true; // Use shell protocol if it's supported and the caller doesn't explicitly // disable it. if (!disable_shell_protocol) { auto&& features = adb_get_feature_set(nullptr); if (features) { use_shell_protocol = CanUseFeature(*features, kFeatureShell2); } else { // Device was unreachable. attempt_connection = false; } } if (attempt_connection) { std::string error; std::string service_string = ShellServiceString(use_shell_protocol, "", command); // 将命令发送给adbd,由adbd执(注意adb运行在Host端,比如PC。adbd才是运行在Android系统上的服务) fd.reset(adb_connect(service_string, &error)); if (fd >= 0) { break; } } fprintf(stderr, "- waiting for device -\n"); if (!wait_for_device("wait-for-device")) { return 1; } } return read_and_dump(fd.get(), use_shell_protocol, callback); }
adbd(daemon进程)在收到Client端(adb)请求,并执行相关动作。在函数StartCommandInProcess中,执行客户端发过来的 “shell pm … /data/local/temp/xxx.apk"命令。
int main(int argc, char* const argv[]) { signal(SIGPIPE, SIG_IGN); int fd = STDIN_FILENO; std::string data; while (true) { std::string error; // 读取客户端的请求 if (!ReadProtocolString(fd, &data, &error)) { PLOG(ERROR) << "Failed to read message: " << error; break; } std::string_view name = data; auto protocol = SubprocessProtocol::kShell; if (android::base::ConsumePrefix(&name, "abb:")) { protocol = SubprocessProtocol::kShell; } else if (android::base::ConsumePrefix(&name, "abb_exec:")) { protocol = SubprocessProtocol::kNone; } else { LOG(FATAL) << "Unknown command prefix for abb: " << data; } // 处理请求命令,具体实现可以参考源码。 // 基本上就是创建了一个Process,在Process中执行传过来的命令。 unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol); int max_buf = LINUX_MAX_SOCKET_SIZE; adb_setsockopt(result, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf)); // 处理结果发送给客户端 if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) { PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data; break; } } }
上述流程中最终执行的是 pm install -r -t -d /data/local/tmp/linduo.apk。Android pm命令实际上是一段bash程序。实现在frameworks/base/cmds/pm/pm中,只是简单的调用了cmd package,并将入参传了进去。
#!/system/bin/sh
cmd package "$@"
cmd是一个bin程序,其实现在frameworks/native/cmds/cmd/中。
# frameworks/native/cmds/cmd/Android.bp package { default_applicable_licenses: ["frameworks_native_cmds_cmd_license"], } // Added automatically by a large-scale-change // See: http://go/android-license-faq license { name: "frameworks_native_cmds_cmd_license", visibility: [":__subpackages__"], license_kinds: [ "SPDX-license-identifier-Apache-2.0", ], license_text: [ "NOTICE", ], } cc_library_static { name: "libcmd", srcs: ["cmd.cpp"], export_include_dirs: ["."], shared_libs: [ "libutils", "liblog", "libselinux", "libbinder", ], cflags: [ "-Wall", "-Werror", "-DXP_UNIX", ], } cc_binary { name: "cmd", srcs: ["main.cpp"], static_libs: [ "libcmd", ], shared_libs: [ "libutils", "liblog", "libselinux", "libbinder", ], cflags: [ "-Wall", "-Werror", "-DXP_UNIX", ], }
如果调用的是cmd package,cmd程序中会通过Android 的ServiceManager连接到PMS服务。然后将命令通过binder发送给PMS服务。
// frameworks/native/cmds/cmd/main.cpp #include <unistd.h> #include "cmd.h" int main(int argc, char* const argv[]) { signal(SIGPIPE, SIG_IGN); // 这里将入参的第一个参数去掉。比如 cmd package xxxxx,去掉后就是 package xxxx std::vector<std::string_view> arguments; arguments.reserve(argc - 1); // 0th argument is a program name, skipping. for (int i = 1; i < argc; ++i) { arguments.emplace_back(argv[i]); } // main程序中调用cmdMain return cmdMain(arguments, android::aout, android::aerr, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, RunMode::kStandalone); } // frameworks/native/cmds/cmd/cmd.cpp int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog, int in, int out, int err, RunMode runMode) { sp<ProcessState> proc = ProcessState::self(); proc->startThreadPool(); #if DEBUG ALOGD("cmd: starting"); #endif // 获取ServiceManager对象 sp<IServiceManager> sm = defaultServiceManager(); // 这里判断一下,cmd命令中想要调用的服务在当前系统中是否存在。不存在则返回 if ((argc == 1) && (argv[0] == "-l")) { Vector<String16> services = sm->listServices(); services.sort(sort_func); outputLog << "Currently running services:" << endl; for (size_t i=0; i<services.size(); i++) { sp<IBinder> service = sm->checkService(services[i]); if (service != nullptr) { outputLog << " " << services[i] << endl; } } return 0; } // 判断是否输入了-w选项。 bool waitForService = ((argc > 1) && (argv[0] == "-w")); int serviceIdx = (waitForService) ? 1 : 0; const auto cmd = argv[serviceIdx]; Vector<String16> args; String16 serviceName = String16(cmd.data(), cmd.size()); for (int i = serviceIdx + 1; i < argc; i++) { args.add(String16(argv[i].data(), argv[i].size())); } sp<IBinder> service; if(waitForService) { service = sm->waitForService(serviceName); } else { service = sm->checkService(serviceName); } if (service == nullptr) { if (runMode == RunMode::kStandalone) { ALOGW("Can't find service %.*s", static_cast<int>(cmd.size()), cmd.data()); } errorLog << "cmd: Can't find service: " << cmd << endl; return 20; } sp<MyShellCallback> cb = new MyShellCallback(errorLog); sp<MyResultReceiver> result = new MyResultReceiver(); #if DEBUG ALOGD("cmd: Invoking %.*s in=%d, out=%d, err=%d", static_cast<int>(cmd.size()), cmd.data(), in, out, err); #endif // 这里将命令发送给对应的服务端执行。 // TODO: block until a result is returned to MyResultReceiver. status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result); // 省略... }
adb将安装apk的命令发送到adbd(服务端),adbd通过binder调用PMS服务安装APK。PMS接收到shell调用后,会创建PackageManagerShellCommand对象并调用它exec函数的进行处理。
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new PackageManagerShellCommand(this, mContext,mDomainVerificationManager.getShell()))
.exec(this, in, out, err, args, callback, resultReceiver);
}
PackageManagerShellCommand的exec函数,有其继承的父类定义。该函数中会调用onCommand解析命令并调用不同的处理分支。对于本文中的情况(执行INSTALL_PUSH方式安装)会调用runInstall函数进行处理。runInstall函数中调用makeInstallParams将组织APK安装的参数,然后调用doRunInstall进程安装。
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @Override public int onCommand(String cmd) { if (cmd == null) { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); try { switch (cmd) { case "path": return runPath(); case "dump": return runDump(); case "list": return runList(); case "resolve-activity": return runResolveActivity(); case "query-activities": return runQueryIntentActivities(); case "query-services": return runQueryIntentServices(); case "query-receivers": return runQueryIntentReceivers(); case "install": return runInstall(); case "install-streaming": return runStreamingInstall(); case "install-incremental": return runIncrementalInstall(); // 省略... } catch (RemoteException e) { pw.println("Remote exception: " + e); } return -1; } private int runInstall() throws RemoteException { return doRunInstall(makeInstallParams()); }
makeInstallParams函数会根据adb install [apk相关参数] 时输入的参数进行组织。其实现如下
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java // 例如: adb install -t -r -d linduo.apk(注意安装路径会被替换成 /data/local/temp/linduo.apk ) private InstallParams makeInstallParams() { final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); final InstallParams params = new InstallParams(); params.sessionParams = sessionParams; // Allowlist all permissions by default sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; String opt; boolean replaceExisting = true; boolean forceNonStaged = false; while ((opt = getNextOption()) != null) { switch (opt) { case "-r": // ignore break; case "-R": replaceExisting = false; break; case "-i": params.installerPackageName = getNextArg(); if (params.installerPackageName == null) { throw new IllegalArgumentException("Missing installer package"); } break; case "-t": sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST; break; case "-f": sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL; break; case "-d": sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; break; case "-g": sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; break; case "--restrict-permissions": sessionParams.installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; break; case "--dont-kill": sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP; break; case "--originating-uri": sessionParams.originatingUri = Uri.parse(getNextArg()); break; case "--referrer": sessionParams.referrerUri = Uri.parse(getNextArg()); break; case "-p": sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING; sessionParams.appPackageName = getNextArg(); if (sessionParams.appPackageName == null) { throw new IllegalArgumentException("Missing inherit package name"); } break; case "--pkg": sessionParams.appPackageName = getNextArg(); if (sessionParams.appPackageName == null) { throw new IllegalArgumentException("Missing package name"); } break; case "-S": final long sizeBytes = Long.parseLong(getNextArg()); if (sizeBytes <= 0) { throw new IllegalArgumentException("Size must be positive"); } sessionParams.setSize(sizeBytes); break; case "--abi": sessionParams.abiOverride = checkAbiArgument(getNextArg()); break; case "--ephemeral": case "--instant": case "--instantapp": sessionParams.setInstallAsInstantApp(true /*isInstantApp*/); break; case "--full": sessionParams.setInstallAsInstantApp(false /*isInstantApp*/); break; case "--preload": sessionParams.setInstallAsVirtualPreload(); break; case "--user": params.userId = UserHandle.parseUserArg(getNextArgRequired()); break; case "--install-location": sessionParams.installLocation = Integer.parseInt(getNextArg()); break; case "--install-reason": sessionParams.installReason = Integer.parseInt(getNextArg()); break; case "--force-uuid": sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID; sessionParams.volumeUuid = getNextArg(); if ("internal".equals(sessionParams.volumeUuid)) { sessionParams.volumeUuid = null; } break; case "--force-sdk": // ignore break; case "--apex": sessionParams.setInstallAsApex(); sessionParams.setStaged(); break; case "--force-non-staged": forceNonStaged = true; break; case "--multi-package": sessionParams.setMultiPackage(); break; case "--staged": sessionParams.setStaged(); break; case "--force-queryable": sessionParams.setForceQueryable(); break; case "--enable-rollback": if (params.installerPackageName == null) { // com.android.shell has the TEST_MANAGE_ROLLBACKS // permission needed to enable rollback for non-module // packages, which is likely what the user wants when // enabling rollback through the shell command. Set // the installer to com.android.shell if no installer // has been provided so that the user doesn't have to // remember to set it themselves. params.installerPackageName = "com.android.shell"; } sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; break; case "--staged-ready-timeout": params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); break; case "--skip-verification": sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION; break; default: throw new IllegalArgumentException("Unknown option " + opt); } } if (replaceExisting) { sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; } if (forceNonStaged) { sessionParams.isStaged = false; } return params; }
doRunInstall函数根据安装参数进行APK的安装,该函数主要做了两个事情。一个是通过doCreateSession函数,创建了PackageInstallerSession对象,做了些Apk安装准工作。另一个是通过doCommitSession函数,利用PackageInstaller.Session对象进行apk的安装。
private int doRunInstall(final InstallParams params) throws RemoteException { final PrintWriter pw = getOutPrintWriter(); // 判断安装类型 final boolean isStreaming = params.sessionParams.dataLoaderParams != null; final boolean isApex = (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; ArrayList<String> args = getRemainingArgs(); final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0)); final boolean hasSplits = args.size() > 1; if (fromStdIn && params.sessionParams.sizeBytes == -1) { pw.println("Error: must either specify a package size or an APK file"); return 1; } if (isApex && hasSplits) { pw.println("Error: can't specify SPLIT(s) for APEX"); return 1; } if (!isStreaming) { if (fromStdIn && hasSplits) { pw.println("Error: can't specify SPLIT(s) along with STDIN"); return 1; } if (args.isEmpty()) { args.add(STDIN_PATH); } else { setParamsSize(params, args); } } // 创建SessionID(PMS会创建PackageInstallerSession对象),可以理解成创建了安装APK的任务 // 通过调用PackageInstallerService的createSession实现 final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); boolean abandonSession = true; try { if (isStreaming) { if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex) != PackageInstaller.STATUS_SUCCESS) { return 1; } } else { if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex) != PackageInstaller.STATUS_SUCCESS) { return 1; } } // 安装APK(通过提交sessionID),主要关注这个函数。 if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } abandonSession = false; if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) { return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw); } pw.println("Success"); return 0; } finally { if (abandonSession) { try { doAbandonSession(sessionId, false /*logSuccess*/); } catch (Exception ignore) { } } } }
doCommitSession函数中创建了PackageInstaller.Session对象,通过与上面创建的sessionId进行绑定。然后调用PackageInstaller.Session.commit进行APK安装。
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)); if (!session.isMultiPackage() && !session.isStaged()) { // Validity check that all .dm files match an apk. // (The installer does not support standalone .dm files and will not process them.) try { DexMetadataHelper.validateDexPaths(session.getNames()); } catch (IllegalStateException | IOException e) { pw.println( "Warning [Could not validate the dex paths: " + e.getMessage() + "]"); } } final LocalIntentReceiver receiver = new LocalIntentReceiver(); //调用commit安装APK session.commit(receiver.getIntentSender()); final Intent result = receiver.getResult(); final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); // 判断APK安装状态 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); } }
PackageInstaller.Session的实现如下,调用了IPackageInstallerSession(通过mInterface.getPackageInstaller().openSession(sessionId)取得)对象的commit函数。
public static class Session implements Closeable {
public Session(IPackageInstallerSession session) {
mSession = session;
}
public void commit(@NonNull IntentSender statusReceiver) {
try {
mSession.commit(statusReceiver, false);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
PackageInstallerSession的commit函数,实现在"frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java“。commit函数中,会将处理转到自身的Handle中。通过一系列调用commit -> dispatchSessionSealed -> handleSessionSealed -> dispatchStreamValidateAndCommit -> handleStreamValidateAndCommit -> handleInstall -> verify -> verifyNonStaged,在verifyNonStaged函数中,调用PMS的verifyStage验证APK。验证成功后,通过onVerificationComplete回调,调用install函数,安装APK
// frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java @Override public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) { // 省略 dispatchSessionSealed(); } private void dispatchSessionSealed() { // 转到Handle线程处理 mHandler.obtainMessage(MSG_ON_SESSION_SEALED).sendToTarget(); } private void handleSessionSealed() { assertSealed("dispatchSessionSealed"); // Persist the fact that we've sealed ourselves to prevent // mutations of any hard links we create. mCallback.onSessionSealedBlocking(this); dispatchStreamValidateAndCommit(); } private void dispatchStreamValidateAndCommit() { mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget(); } private void handleStreamValidateAndCommit() { // 省略 mHandler.obtainMessage(MSG_INSTALL).sendToTarget(); } private void handleInstall() { // 检查、验证APK包 verify(); } private void verify() { try { verifyNonStaged(); } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); onSessionVerificationFailure(e.error, completeMsg); } } // 调用PMS的verifyStage,验证APK。验证成功会,调用install方法进行安装。 private void verifyNonStaged() throws PackageManagerException { final PackageManagerService.VerificationParams verifyingSession = prepareForVerification(); if (verifyingSession == null) { return; } if (isMultiPackage()) { // 省略 mPm.verifyStage(verifyingSession, verifyingChildSessions); } else { mPm.verifyStage(verifyingSession); } } // 验证成功,通过回调。调用install开始安装APK private void onVerificationComplete() { // Staged sessions will be installed later during boot if (isStaged()) { // TODO(b/136257624): Remove this once all verification logic has been transferred out // of StagingManager. mStagingManager.notifyPreRebootVerification_Apk_Complete(mStagedSession); // TODO(b/136257624): We also need to destroy internals for verified staged session, // otherwise file descriptors are never closed for verified staged session until reboot return; } install(); }
在install函数中,调用了PMS的installStage函数,对APK进行了安装。
// frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java private void install() { try { installNonStaged(); } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); onSessionInstallationFailure(e.error, completeMsg); } } 调用PMS的installStage函数,安装APK private void installNonStaged() throws PackageManagerException { final PackageManagerService.InstallParams installingSession = makeInstallParams(); if (installingSession == null) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session should contain at least one apk session for installation"); } if (isMultiPackage()) { // 省略... mPm.installStage(installingSession, installingChildSessions); } else { mPm.installStage(installingSession); } }
PackageManagerService的installStage会对APK进行实际的安装。
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void installStage(InstallParams params) {
// 首先进行copy
final Message msg = mHandler.obtainMessage(INIT_COPY);
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);
}
转Handle处理INIT_COPY,调用startCopy函数,在startCopy函数中调用handleStartCopy和handleReturnCode进行APK的拷贝,从/data/local/tmp/目录把APK文件拷贝拷贝到/data/app/包名/目录。然后调用processInstallRequestsAsync进行安装。
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java private abstract class HandlerParams { final void startCopy() { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this); handleStartCopy(); handleReturnCode(); } } class InstallParams extends HandlerParams { // 根据安装Flag,进行预处理 public void handleStartCopy() { if ((installFlags & PackageManager.INSTALL_APEX) != 0) { mRet = INSTALL_SUCCEEDED; return; } PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext, mPackageLite, origin.resolvedPath, installFlags, packageAbiOverride); // For staged session, there is a delay between its verification and install. Device // state can change within this delay and hence we need to re-verify certain conditions. boolean isStaged = (installFlags & INSTALL_STAGED) != 0; if (isStaged) { mRet = verifyReplacingVersionCode( pkgLite, requiredInstalledVersionCode, installFlags); if (mRet != INSTALL_SUCCEEDED) { return; } } mRet = overrideInstallLocation(pkgLite); } @Override void handleReturnCode() { processPendingInstall(); } private void processPendingInstall() { InstallArgs args = createInstallArgs(this); if (mRet == PackageManager.INSTALL_SUCCEEDED) { // 这里会对apk进行拷贝。拷贝到/data/app/包名/ 目录下 mRet = args.copyApk(); } if (mRet == PackageManager.INSTALL_SUCCEEDED) { // 解压apk相关的一些资源 F2fsUtils.releaseCompressedBlocks( mContext.getContentResolver(), new File(args.getCodePath())); } if (mParentInstallParams != null) { // 安装多个APK mParentInstallParams.tryProcessInstallRequest(args, mRet); } else { // 安装一个APK PackageInstalledInfo res = createPackageInstalledInfo(mRet); processInstallRequestsAsync( res.returnCode == PackageManager.INSTALL_SUCCEEDED, Collections.singletonList(new InstallRequest(args, res))); } } }
processInstallRequestsAsync 异步安装APK。最终会调用PMS的installPackagesLI函数进行安装。安装流程包括四个流程:Prepare、Scan、Reconcile、Commit。安装后系统关于该APK的信息会更新,启动该APK时会以新的信息进行启动(安装成功状态)。
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java // Queue up an async operation since the package installation may take a little while. private void processInstallRequestsAsync(boolean success, List<InstallRequest> installRequests) { mHandler.post(() -> { // 省略 for (InstallRequest request : apkInstallRequests) { restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult, new PostInstallData(request.args, request.installResult, null)); } }); } // Queue up an async operation since the package installation may take a little while. private void processInstallRequestsAsync(boolean success, List<InstallRequest> installRequests) { mHandler.post(() -> { // 省略... if (success) { for (InstallRequest request : apkInstallRequests) { request.args.doPreInstall(request.installResult.returnCode); } synchronized (mInstallLock) { // 安装APK installPackagesTracedLI(apkInstallRequests); } for (InstallRequest request : apkInstallRequests) { request.args.doPostInstall( request.installResult.returnCode, request.installResult.uid); } } for (InstallRequest request : apkInstallRequests) { restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult, new PostInstallData(request.args, request.installResult, null)); } }); } @GuardedBy("mInstallLock") private void installPackagesTracedLI(List<InstallRequest> requests) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages"); installPackagesLI(requests); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } @GuardedBy("mInstallLock") private void installPackagesLI(List<InstallRequest> requests) { // 省略.. // 安装APK Prepare-> Scan -> Reconcile -> Commit // Prepare: Analyzes any current install state, parses the package and does initial // Scan:Interrogates the parsed packages given the context collected in prepare // Reconcile:Validates scanned packages in the context of each other and the current system // state to ensure that the install will be successful // Commit:Commits all scanned packages and updates system state. }
通过adb install安装apk,大概流程是 adb(client)端通过socke命令给adbd(service),然后adbd通过ServiceManager以Binder方式将命令发送给PackageManagerService。PackageManagerService解析命令,复制APK及相关资源到指定路径,并更新系统中APK相关配置信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。