Loading cmds/installd/dexopt.cpp +415 −372 Original line number Original line Diff line number Diff line Loading @@ -201,24 +201,54 @@ static const char* get_location_from_path(const char* path) { } } } } // Automatically adds binary and null terminator arg. // ExecVHelper prepares and holds pointers to parsed command line arguments so that no allocations static inline void ExecVWithArgs(const char* bin, const std::vector<std::string>& args) { // need to be performed between the fork and exec. std::vector<const char*> argv = {bin}; class ExecVHelper { for (const std::string& arg : args) { public: argv.push_back(arg.c_str()); // Store a placeholder for the binary name. ExecVHelper() : args_(1u, std::string()) {} void PrepareArgs(const std::string& bin) { CHECK(!args_.empty()); CHECK(args_[0].empty()); args_[0] = bin; // Write char* into array. for (const std::string& arg : args_) { argv_.push_back(arg.c_str()); } } // Add null terminator. argv_.push_back(nullptr); // Add null terminator. argv.push_back(nullptr); execv(bin, (char * const *)&argv[0]); } } static inline void AddArgIfNonEmpty(const std::string& arg, std::vector<std::string>* args) { [[ noreturn ]] DCHECK(args != nullptr); void Exec(int exit_code) { execv(argv_[0], (char * const *)&argv_[0]); PLOG(ERROR) << "execv(" << argv_[0] << ") failed"; exit(exit_code); } // Add an arg if it's not empty. void AddArg(const std::string& arg) { if (!arg.empty()) { if (!arg.empty()) { args->push_back(arg); args_.push_back(arg); } } } } // Add a runtime arg if it's not empty. void AddRuntimeArg(const std::string& arg) { if (!arg.empty()) { args_.push_back("--runtime-arg"); args_.push_back(arg); } } protected: // Holder arrays for backing arg storage. std::vector<std::string> args_; // Argument poiners. std::vector<const char*> argv_; }; static std::string MapPropertyToArg(const std::string& property, static std::string MapPropertyToArg(const std::string& property, const std::string& format, const std::string& format, const std::string& default_value = "") { const std::string& default_value = "") { Loading @@ -229,13 +259,28 @@ static std::string MapPropertyToArg(const std::string& property, return ""; return ""; } } [[ noreturn ]] class RunDex2Oat : public ExecVHelper { static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd, public: const char* input_file_name, const char* output_file_name, int swap_fd, RunDex2Oat(int zip_fd, const char* instruction_set, const char* compiler_filter, int oat_fd, bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd, int input_vdex_fd, const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks, int output_vdex_fd, bool generate_compact_dex, int dex_metadata_fd, const char* compilation_reason) { int image_fd, const char* input_file_name, const char* output_file_name, int swap_fd, const char* instruction_set, const char* compiler_filter, bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd, const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks, bool generate_compact_dex, int dex_metadata_fd, const char* compilation_reason) { // Get the relative path to the input file. // Get the relative path to the input file. const char* relative_input_file_name = get_location_from_path(input_file_name); const char* relative_input_file_name = get_location_from_path(input_file_name); Loading Loading @@ -286,15 +331,15 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd constexpr const char* kDex2oatDebugPath = "/system/bin/dex2oatd"; constexpr const char* kDex2oatDebugPath = "/system/bin/dex2oatd"; // Do not use dex2oatd for release candidates (give dex2oat more soak time). // Do not use dex2oatd for release candidates (give dex2oat more soak time). bool is_release = android::base::GetProperty("ro.build.version.codename", "") == "REL"; bool is_release = android::base::GetProperty("ro.build.version.codename", "") == "REL"; if (is_debug_runtime() || (background_job_compile && is_debuggable_build() && !is_release)) { if (is_debug_runtime() || (background_job_compile && is_debuggable_build() && !is_release)) { if (access(kDex2oatDebugPath, X_OK) == 0) { if (access(kDex2oatDebugPath, X_OK) == 0) { dex2oat_bin = kDex2oatDebugPath; dex2oat_bin = kDex2oatDebugPath; } } } } bool generate_minidebug_info = kEnableMinidebugInfo && bool generate_minidebug_info = kEnableMinidebugInfo && android::base::GetBoolProperty(kMinidebugInfoSystemProperty, GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault); kMinidebugInfoSystemPropertyDefault); // clang FORTIFY doesn't let us use strlen in constant array bounds, so we // clang FORTIFY doesn't let us use strlen in constant array bounds, so we // use arraysize instead. // use arraysize instead. Loading @@ -314,7 +359,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd } } std::string class_loader_context_arg; std::string class_loader_context_arg; if (class_loader_context != nullptr) { if (class_loader_context != nullptr) { class_loader_context_arg = StringPrintf("--class-loader-context=%s", class_loader_context); class_loader_context_arg = StringPrintf("--class-loader-context=%s", class_loader_context); } } if (swap_fd >= 0) { if (swap_fd >= 0) { Loading Loading @@ -369,72 +415,64 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd // supported. // supported. const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd); const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd); std::vector<std::string> args = { AddArg(zip_fd_arg); zip_fd_arg, AddArg(zip_location_arg); zip_location_arg, AddArg(input_vdex_fd_arg); input_vdex_fd_arg, AddArg(output_vdex_fd_arg); output_vdex_fd_arg, AddArg(oat_fd_arg); oat_fd_arg, AddArg(oat_location_arg); oat_location_arg, AddArg(instruction_set_arg); instruction_set_arg, }; auto add_runtime_arg = [&](const std::string& arg) { args.push_back("--runtime-arg"); args.push_back(arg); }; AddArgIfNonEmpty(instruction_set_variant_arg, &args); AddArg(instruction_set_variant_arg); AddArgIfNonEmpty(instruction_set_features_arg, &args); AddArg(instruction_set_features_arg); if (!dex2oat_Xms_arg.empty()) { add_runtime_arg(dex2oat_Xms_arg); AddRuntimeArg(dex2oat_Xms_arg); } AddRuntimeArg(dex2oat_Xmx_arg); if (!dex2oat_Xmx_arg.empty()) { add_runtime_arg(dex2oat_Xmx_arg); AddArg(resolve_startup_string_arg); } AddArg(dex2oat_compiler_filter_arg); AddArgIfNonEmpty(resolve_startup_string_arg, &args); AddArg(dex2oat_threads_arg); AddArgIfNonEmpty(dex2oat_compiler_filter_arg, &args); AddArg(dex2oat_swap_fd); AddArgIfNonEmpty(dex2oat_threads_arg, &args); AddArg(dex2oat_image_fd); AddArgIfNonEmpty(dex2oat_swap_fd, &args); AddArgIfNonEmpty(dex2oat_image_fd, &args); if (generate_debug_info) { if (generate_debug_info) { args.push_back("--generate-debug-info"); AddArg("--generate-debug-info"); } } if (debuggable) { if (debuggable) { args.push_back("--debuggable"); AddArg("--debuggable"); } } AddArgIfNonEmpty(image_format_arg, &args); AddArg(image_format_arg); AddArgIfNonEmpty(dex2oat_large_app_threshold_arg, &args); AddArg(dex2oat_large_app_threshold_arg); args.insert(args.end(), dex2oat_flags_args.begin(), dex2oat_flags_args.end()); if (have_dex2oat_relocation_skip_flag) { if (have_dex2oat_relocation_skip_flag) { add_runtime_arg(dex2oat_norelocation); AddRuntimeArg(dex2oat_norelocation); } } AddArgIfNonEmpty(profile_arg, &args); AddArg(profile_arg); AddArgIfNonEmpty(base_dir, &args); AddArg(base_dir); AddArgIfNonEmpty(class_loader_context_arg, &args); AddArg(class_loader_context_arg); if (generate_minidebug_info) { if (generate_minidebug_info) { args.push_back(kMinidebugDex2oatFlag); AddArg(kMinidebugDex2oatFlag); } } if (disable_cdex) { if (disable_cdex) { args.push_back(kDisableCompactDexFlag); AddArg(kDisableCompactDexFlag); } } AddArgIfNonEmpty(target_sdk_version_arg, &args); AddArg(target_sdk_version_arg); if (enable_hidden_api_checks) { if (enable_hidden_api_checks) { add_runtime_arg("-Xhidden-api-checks"); AddRuntimeArg("-Xhidden-api-checks"); } } if (dex_metadata_fd > -1) { if (dex_metadata_fd > -1) { args.push_back(dex_metadata_fd_arg); AddArg(dex_metadata_fd_arg); } } AddArgIfNonEmpty(compilation_reason_arg, &args); AddArg(compilation_reason_arg); // Do not add after dex2oat_flags, they should override others for debugging. // Do not add args after dex2oat_flags, they should override others for debugging. args_.insert(args_.end(), dex2oat_flags_args.begin(), dex2oat_flags_args.end()); ExecVWithArgs(dex2oat_bin, args); PrepareArgs(dex2oat_bin); PLOG(ERROR) << "execv(" << dex2oat_bin << ") failed"; exit(DexoptReturnCodes::kDex2oatExec); } } }; /* /* * Whether dexopt should use a swap file when compiling an APK. * Whether dexopt should use a swap file when compiling an APK. Loading Loading @@ -610,75 +648,92 @@ static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; [[ noreturn ]] class RunProfman : public ExecVHelper { static void run_profman(const std::vector<unique_fd>& profile_fds, public: void SetupArgs(const std::vector<unique_fd>& profile_fds, const unique_fd& reference_profile_fd, const unique_fd& reference_profile_fd, const std::vector<unique_fd>* apk_fds, const std::vector<unique_fd>& apk_fds, const std::vector<std::string>* dex_locations, const std::vector<std::string>& dex_locations, bool copy_and_update) { bool copy_and_update) { const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman"; const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman"; if (copy_and_update) { if (copy_and_update) { CHECK_EQ(1u, profile_fds.size()); CHECK_EQ(1u, profile_fds.size()); CHECK(apk_fds != nullptr); CHECK_EQ(1u, apk_fds.size()); CHECK_EQ(1u, apk_fds->size()); } if (reference_profile_fd != -1) { AddArg("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get())); } } std::vector<std::string> args; args.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get())); for (const unique_fd& fd : profile_fds) { for (const unique_fd& fd : profile_fds) { args.push_back("--profile-file-fd=" + std::to_string(fd.get())); AddArg("--profile-file-fd=" + std::to_string(fd.get())); } } if (apk_fds != nullptr) { for (const unique_fd& fd : apk_fds) { for (const unique_fd& fd : *apk_fds) { AddArg("--apk-fd=" + std::to_string(fd.get())); args.push_back("--apk-fd=" + std::to_string(fd.get())); } } } std::vector<std::string> dex_location_args; for (const std::string& dex_location : dex_locations) { if (dex_locations != nullptr) { AddArg("--dex-location=" + dex_location); for (const std::string& dex_location : *dex_locations) { args.push_back("--dex-location=" + dex_location); } } } if (copy_and_update) { if (copy_and_update) { args.push_back("--copy-and-update-profile-key"); AddArg("--copy-and-update-profile-key"); } } // Do not add after dex2oat_flags, they should override others for debugging. // Do not add after dex2oat_flags, they should override others for debugging. PrepareArgs(profman_bin); ExecVWithArgs(profman_bin, args); PLOG(ERROR) << "execv(" << profman_bin << ") failed"; exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */ } } [[ noreturn ]] void SetupMerge(const std::vector<unique_fd>& profiles_fd, static void run_profman_merge(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd, const unique_fd& reference_profile_fd, const std::vector<unique_fd>* apk_fds = nullptr, const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(), const std::vector<std::string>* dex_locations = nullptr) { const std::vector<std::string>& dex_locations = std::vector<std::string>()) { run_profman(profiles_fd, reference_profile_fd, apk_fds, dex_locations, SetupArgs(profiles_fd, /*copy_and_update*/false); reference_profile_fd, apk_fds, dex_locations, /*copy_and_update=*/false); } } [[ noreturn ]] void SetupCopyAndUpdate(unique_fd&& profile_fd, static void run_profman_copy_and_update(unique_fd&& profile_fd, unique_fd&& reference_profile_fd, unique_fd&& reference_profile_fd, unique_fd&& apk_fd, unique_fd&& apk_fd, const std::string& dex_location) { const std::string& dex_location) { std::vector<unique_fd> profiles_fd; // The fds need to stay open longer than the scope of the function, so put them into a local profiles_fd.push_back(std::move(profile_fd)); // variable vector. std::vector<unique_fd> apk_fds; profiles_fd_.push_back(std::move(profile_fd)); apk_fds.push_back(std::move(apk_fd)); apk_fds_.push_back(std::move(apk_fd)); std::vector<std::string> dex_locations; reference_profile_fd_ = std::move(reference_profile_fd); dex_locations.push_back(dex_location); std::vector<std::string> dex_locations = {dex_location}; SetupArgs(profiles_fd_, reference_profile_fd_, apk_fds_, dex_locations, /*copy_and_update=*/true); } void SetupDump(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd, const std::vector<std::string>& dex_locations, const std::vector<unique_fd>& apk_fds, const unique_fd& output_fd) { AddArg("--dump-only"); AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get())); SetupArgs(profiles_fd, reference_profile_fd, apk_fds, dex_locations, /*copy_and_update=*/false); } run_profman(profiles_fd, reference_profile_fd, &apk_fds, &dex_locations, void Exec() { /*copy_and_update*/true); ExecVHelper::Exec(DexoptReturnCodes::kProfmanExec); } } private: unique_fd reference_profile_fd_; std::vector<unique_fd> profiles_fd_; std::vector<unique_fd> apk_fds_; }; // Decides if profile guided compilation is needed or not based on existing profiles. // Decides if profile guided compilation is needed or not based on existing profiles. // The location is the package name for primary apks or the dex path for secondary dex files. // The location is the package name for primary apks or the dex path for secondary dex files. // Returns true if there is enough information in the current profiles that makes it // Returns true if there is enough information in the current profiles that makes it Loading @@ -697,11 +752,13 @@ static bool analyze_profiles(uid_t uid, const std::string& package_name, return false; return false; } } RunProfman profman_merge; profman_merge.SetupMerge(profiles_fd, reference_profile_fd); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(uid); drop_capabilities(uid); run_profman_merge(profiles_fd, reference_profile_fd); profman_merge.Exec(); } } /* parent */ /* parent */ int return_code = wait_child(pid); int return_code = wait_child(pid); Loading Loading @@ -774,35 +831,6 @@ bool analyze_primary_profiles(uid_t uid, const std::string& package_name, return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false); return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false); } } [[ noreturn ]] static void run_profman_dump(const std::vector<unique_fd>& profile_fds, const unique_fd& reference_profile_fd, const std::vector<std::string>& dex_locations, const std::vector<unique_fd>& apk_fds, const unique_fd& output_fd) { std::vector<std::string> profman_args; static const char* PROFMAN_BIN = "/system/bin/profman"; profman_args.push_back("--dump-only"); profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get())); if (reference_profile_fd != -1) { profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd.get())); } for (size_t i = 0; i < profile_fds.size(); i++) { profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get())); } for (const std::string& dex_location : dex_locations) { profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str())); } for (size_t i = 0; i < apk_fds.size(); i++) { profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get())); } ExecVWithArgs(PROFMAN_BIN, profman_args); PLOG(ERROR) << "execv(" << PROFMAN_BIN << ") failed"; exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */ } bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name, bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name, const std::string& code_path) { const std::string& code_path) { std::vector<unique_fd> profile_fds; std::vector<unique_fd> profile_fds; Loading Loading @@ -839,12 +867,13 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& p apk_fds.push_back(std::move(apk_fd)); apk_fds.push_back(std::move(apk_fd)); RunProfman profman_dump; profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds, output_fd); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(uid); drop_capabilities(uid); run_profman_dump(profile_fds, reference_profile_fd, dex_locations, profman_dump.Exec(); apk_fds, output_fd); } } /* parent */ /* parent */ int return_code = wait_child(pid); int return_code = wait_child(pid); Loading Loading @@ -1416,9 +1445,16 @@ void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter. // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter. // If this is for a profile guided compilation, profile_was_updated will tell whether or not // If this is for a profile guided compilation, profile_was_updated will tell whether or not // the profile has changed. // the profile has changed. static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oat_fd, class RunDexoptAnalyzer : public ExecVHelper { int zip_fd, const std::string& instruction_set, const std::string& compiler_filter, public: bool profile_was_updated, bool downgrade, RunDexoptAnalyzer(const std::string& dex_file, int vdex_fd, int oat_fd, int zip_fd, const std::string& instruction_set, const std::string& compiler_filter, bool profile_was_updated, bool downgrade, const char* class_loader_context) { const char* class_loader_context) { CHECK_GE(zip_fd, 0); CHECK_GE(zip_fd, 0); const char* dexoptanalyzer_bin = const char* dexoptanalyzer_bin = Loading @@ -1440,31 +1476,29 @@ static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oa } } // program name, dex file, isa, filter // program name, dex file, isa, filter std::vector<std::string> args = { AddArg(dex_file_arg); dex_file_arg, AddArg(isa_arg); isa_arg, AddArg(compiler_filter_arg); compiler_filter_arg, }; if (oat_fd >= 0) { if (oat_fd >= 0) { args.push_back(oat_fd_arg); AddArg(oat_fd_arg); } } if (vdex_fd >= 0) { if (vdex_fd >= 0) { args.push_back(vdex_fd_arg); AddArg(vdex_fd_arg); } } args.push_back(zip_fd_arg.c_str()); AddArg(zip_fd_arg.c_str()); if (profile_was_updated) { if (profile_was_updated) { args.push_back(assume_profile_changed); AddArg(assume_profile_changed); } } if (downgrade) { if (downgrade) { args.push_back(downgrade_flag); AddArg(downgrade_flag); } } if (class_loader_context != nullptr) { if (class_loader_context != nullptr) { args.push_back(class_loader_context_arg.c_str()); AddArg(class_loader_context_arg.c_str()); } } ExecVWithArgs(dexoptanalyzer_bin, args); PrepareArgs(dexoptanalyzer_bin); ALOGE("execv(%s) failed: %s\n", dexoptanalyzer_bin, strerror(errno)); } } }; // Prepares the oat dir for the secondary dex files. // Prepares the oat dir for the secondary dex files. static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid, static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid, Loading Loading @@ -1716,7 +1750,9 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char /*is_secondary_dex*/true); /*is_secondary_dex*/true); // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return. // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return. exec_dexoptanalyzer(dex_path, // Note that we do not do it before the fork since opening the files is required to happen // after forking. RunDexoptAnalyzer run_dexopt_analyzer(dex_path, vdex_file_fd.get(), vdex_file_fd.get(), oat_file_fd.get(), oat_file_fd.get(), zip_fd.get(), zip_fd.get(), Loading @@ -1724,8 +1760,7 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char compiler_filter, profile_was_updated, compiler_filter, profile_was_updated, downgrade, downgrade, class_loader_context); class_loader_context); PLOG(ERROR) << "Failed to exec dexoptanalyzer"; run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec); _exit(kSecondaryDexDexoptAnalyzerSkippedFailExec); } } /* parent */ /* parent */ Loading Loading @@ -1894,18 +1929,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---"; LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---"; pid_t pid = fork(); RunDex2Oat runner(input_fd.get(), if (pid == 0) { /* child -- drop privileges before continuing */ drop_capabilities(uid); SetDex2OatScheduling(boot_complete); if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) { PLOG(ERROR) << "flock(" << out_oat_path << ") failed"; _exit(DexoptReturnCodes::kFlock); } run_dex2oat(input_fd.get(), out_oat_fd.get(), out_oat_fd.get(), in_vdex_fd.get(), in_vdex_fd.get(), out_vdex_fd.get(), out_vdex_fd.get(), Loading @@ -1925,6 +1949,19 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins generate_compact_dex, generate_compact_dex, dex_metadata_fd.get(), dex_metadata_fd.get(), compilation_reason); compilation_reason); pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ drop_capabilities(uid); SetDex2OatScheduling(boot_complete); if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) { PLOG(ERROR) << "flock(" << out_oat_path << ") failed"; _exit(DexoptReturnCodes::kFlock); } runner.Exec(DexoptReturnCodes::kDex2oatExec); } else { } else { int res = wait_child(pid); int res = wait_child(pid); if (res == 0) { if (res == 0) { Loading Loading @@ -2488,11 +2525,13 @@ static bool create_app_profile_snapshot(int32_t app_id, return false; return false; } } RunProfman args; args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(app_shared_gid); drop_capabilities(app_shared_gid); run_profman_merge(profiles_fd, snapshot_fd, &apk_fds, &dex_locations); args.Exec(); } } /* parent */ /* parent */ Loading Loading @@ -2572,6 +2611,8 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, profiles_fd.push_back(std::move(fd)); profiles_fd.push_back(std::move(fd)); } } } } RunProfman args; args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ Loading @@ -2579,7 +2620,7 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, // The introduction of new access flags into boot jars causes them to // The introduction of new access flags into boot jars causes them to // fail dex file verification. // fail dex file verification. run_profman_merge(profiles_fd, snapshot_fd, &apk_fds, &dex_locations); args.Exec(); } } /* parent */ /* parent */ Loading Loading @@ -2633,6 +2674,11 @@ bool prepare_app_profile(const std::string& package_name, return false; return false; } } RunProfman args; args.SetupCopyAndUpdate(std::move(dex_metadata_fd), std::move(ref_profile_fd), std::move(apk_fd), code_path); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ Loading @@ -2640,10 +2686,7 @@ bool prepare_app_profile(const std::string& package_name, drop_capabilities(app_shared_gid); drop_capabilities(app_shared_gid); // The copy and update takes ownership over the fds. // The copy and update takes ownership over the fds. run_profman_copy_and_update(std::move(dex_metadata_fd), args.Exec(); std::move(ref_profile_fd), std::move(apk_fd), code_path); } } /* parent */ /* parent */ Loading Loading
cmds/installd/dexopt.cpp +415 −372 Original line number Original line Diff line number Diff line Loading @@ -201,24 +201,54 @@ static const char* get_location_from_path(const char* path) { } } } } // Automatically adds binary and null terminator arg. // ExecVHelper prepares and holds pointers to parsed command line arguments so that no allocations static inline void ExecVWithArgs(const char* bin, const std::vector<std::string>& args) { // need to be performed between the fork and exec. std::vector<const char*> argv = {bin}; class ExecVHelper { for (const std::string& arg : args) { public: argv.push_back(arg.c_str()); // Store a placeholder for the binary name. ExecVHelper() : args_(1u, std::string()) {} void PrepareArgs(const std::string& bin) { CHECK(!args_.empty()); CHECK(args_[0].empty()); args_[0] = bin; // Write char* into array. for (const std::string& arg : args_) { argv_.push_back(arg.c_str()); } } // Add null terminator. argv_.push_back(nullptr); // Add null terminator. argv.push_back(nullptr); execv(bin, (char * const *)&argv[0]); } } static inline void AddArgIfNonEmpty(const std::string& arg, std::vector<std::string>* args) { [[ noreturn ]] DCHECK(args != nullptr); void Exec(int exit_code) { execv(argv_[0], (char * const *)&argv_[0]); PLOG(ERROR) << "execv(" << argv_[0] << ") failed"; exit(exit_code); } // Add an arg if it's not empty. void AddArg(const std::string& arg) { if (!arg.empty()) { if (!arg.empty()) { args->push_back(arg); args_.push_back(arg); } } } } // Add a runtime arg if it's not empty. void AddRuntimeArg(const std::string& arg) { if (!arg.empty()) { args_.push_back("--runtime-arg"); args_.push_back(arg); } } protected: // Holder arrays for backing arg storage. std::vector<std::string> args_; // Argument poiners. std::vector<const char*> argv_; }; static std::string MapPropertyToArg(const std::string& property, static std::string MapPropertyToArg(const std::string& property, const std::string& format, const std::string& format, const std::string& default_value = "") { const std::string& default_value = "") { Loading @@ -229,13 +259,28 @@ static std::string MapPropertyToArg(const std::string& property, return ""; return ""; } } [[ noreturn ]] class RunDex2Oat : public ExecVHelper { static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd, public: const char* input_file_name, const char* output_file_name, int swap_fd, RunDex2Oat(int zip_fd, const char* instruction_set, const char* compiler_filter, int oat_fd, bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd, int input_vdex_fd, const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks, int output_vdex_fd, bool generate_compact_dex, int dex_metadata_fd, const char* compilation_reason) { int image_fd, const char* input_file_name, const char* output_file_name, int swap_fd, const char* instruction_set, const char* compiler_filter, bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd, const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks, bool generate_compact_dex, int dex_metadata_fd, const char* compilation_reason) { // Get the relative path to the input file. // Get the relative path to the input file. const char* relative_input_file_name = get_location_from_path(input_file_name); const char* relative_input_file_name = get_location_from_path(input_file_name); Loading Loading @@ -286,15 +331,15 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd constexpr const char* kDex2oatDebugPath = "/system/bin/dex2oatd"; constexpr const char* kDex2oatDebugPath = "/system/bin/dex2oatd"; // Do not use dex2oatd for release candidates (give dex2oat more soak time). // Do not use dex2oatd for release candidates (give dex2oat more soak time). bool is_release = android::base::GetProperty("ro.build.version.codename", "") == "REL"; bool is_release = android::base::GetProperty("ro.build.version.codename", "") == "REL"; if (is_debug_runtime() || (background_job_compile && is_debuggable_build() && !is_release)) { if (is_debug_runtime() || (background_job_compile && is_debuggable_build() && !is_release)) { if (access(kDex2oatDebugPath, X_OK) == 0) { if (access(kDex2oatDebugPath, X_OK) == 0) { dex2oat_bin = kDex2oatDebugPath; dex2oat_bin = kDex2oatDebugPath; } } } } bool generate_minidebug_info = kEnableMinidebugInfo && bool generate_minidebug_info = kEnableMinidebugInfo && android::base::GetBoolProperty(kMinidebugInfoSystemProperty, GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault); kMinidebugInfoSystemPropertyDefault); // clang FORTIFY doesn't let us use strlen in constant array bounds, so we // clang FORTIFY doesn't let us use strlen in constant array bounds, so we // use arraysize instead. // use arraysize instead. Loading @@ -314,7 +359,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd } } std::string class_loader_context_arg; std::string class_loader_context_arg; if (class_loader_context != nullptr) { if (class_loader_context != nullptr) { class_loader_context_arg = StringPrintf("--class-loader-context=%s", class_loader_context); class_loader_context_arg = StringPrintf("--class-loader-context=%s", class_loader_context); } } if (swap_fd >= 0) { if (swap_fd >= 0) { Loading Loading @@ -369,72 +415,64 @@ static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vd // supported. // supported. const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd); const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd); std::vector<std::string> args = { AddArg(zip_fd_arg); zip_fd_arg, AddArg(zip_location_arg); zip_location_arg, AddArg(input_vdex_fd_arg); input_vdex_fd_arg, AddArg(output_vdex_fd_arg); output_vdex_fd_arg, AddArg(oat_fd_arg); oat_fd_arg, AddArg(oat_location_arg); oat_location_arg, AddArg(instruction_set_arg); instruction_set_arg, }; auto add_runtime_arg = [&](const std::string& arg) { args.push_back("--runtime-arg"); args.push_back(arg); }; AddArgIfNonEmpty(instruction_set_variant_arg, &args); AddArg(instruction_set_variant_arg); AddArgIfNonEmpty(instruction_set_features_arg, &args); AddArg(instruction_set_features_arg); if (!dex2oat_Xms_arg.empty()) { add_runtime_arg(dex2oat_Xms_arg); AddRuntimeArg(dex2oat_Xms_arg); } AddRuntimeArg(dex2oat_Xmx_arg); if (!dex2oat_Xmx_arg.empty()) { add_runtime_arg(dex2oat_Xmx_arg); AddArg(resolve_startup_string_arg); } AddArg(dex2oat_compiler_filter_arg); AddArgIfNonEmpty(resolve_startup_string_arg, &args); AddArg(dex2oat_threads_arg); AddArgIfNonEmpty(dex2oat_compiler_filter_arg, &args); AddArg(dex2oat_swap_fd); AddArgIfNonEmpty(dex2oat_threads_arg, &args); AddArg(dex2oat_image_fd); AddArgIfNonEmpty(dex2oat_swap_fd, &args); AddArgIfNonEmpty(dex2oat_image_fd, &args); if (generate_debug_info) { if (generate_debug_info) { args.push_back("--generate-debug-info"); AddArg("--generate-debug-info"); } } if (debuggable) { if (debuggable) { args.push_back("--debuggable"); AddArg("--debuggable"); } } AddArgIfNonEmpty(image_format_arg, &args); AddArg(image_format_arg); AddArgIfNonEmpty(dex2oat_large_app_threshold_arg, &args); AddArg(dex2oat_large_app_threshold_arg); args.insert(args.end(), dex2oat_flags_args.begin(), dex2oat_flags_args.end()); if (have_dex2oat_relocation_skip_flag) { if (have_dex2oat_relocation_skip_flag) { add_runtime_arg(dex2oat_norelocation); AddRuntimeArg(dex2oat_norelocation); } } AddArgIfNonEmpty(profile_arg, &args); AddArg(profile_arg); AddArgIfNonEmpty(base_dir, &args); AddArg(base_dir); AddArgIfNonEmpty(class_loader_context_arg, &args); AddArg(class_loader_context_arg); if (generate_minidebug_info) { if (generate_minidebug_info) { args.push_back(kMinidebugDex2oatFlag); AddArg(kMinidebugDex2oatFlag); } } if (disable_cdex) { if (disable_cdex) { args.push_back(kDisableCompactDexFlag); AddArg(kDisableCompactDexFlag); } } AddArgIfNonEmpty(target_sdk_version_arg, &args); AddArg(target_sdk_version_arg); if (enable_hidden_api_checks) { if (enable_hidden_api_checks) { add_runtime_arg("-Xhidden-api-checks"); AddRuntimeArg("-Xhidden-api-checks"); } } if (dex_metadata_fd > -1) { if (dex_metadata_fd > -1) { args.push_back(dex_metadata_fd_arg); AddArg(dex_metadata_fd_arg); } } AddArgIfNonEmpty(compilation_reason_arg, &args); AddArg(compilation_reason_arg); // Do not add after dex2oat_flags, they should override others for debugging. // Do not add args after dex2oat_flags, they should override others for debugging. args_.insert(args_.end(), dex2oat_flags_args.begin(), dex2oat_flags_args.end()); ExecVWithArgs(dex2oat_bin, args); PrepareArgs(dex2oat_bin); PLOG(ERROR) << "execv(" << dex2oat_bin << ") failed"; exit(DexoptReturnCodes::kDex2oatExec); } } }; /* /* * Whether dexopt should use a swap file when compiling an APK. * Whether dexopt should use a swap file when compiling an APK. Loading Loading @@ -610,75 +648,92 @@ static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; [[ noreturn ]] class RunProfman : public ExecVHelper { static void run_profman(const std::vector<unique_fd>& profile_fds, public: void SetupArgs(const std::vector<unique_fd>& profile_fds, const unique_fd& reference_profile_fd, const unique_fd& reference_profile_fd, const std::vector<unique_fd>* apk_fds, const std::vector<unique_fd>& apk_fds, const std::vector<std::string>* dex_locations, const std::vector<std::string>& dex_locations, bool copy_and_update) { bool copy_and_update) { const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman"; const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman"; if (copy_and_update) { if (copy_and_update) { CHECK_EQ(1u, profile_fds.size()); CHECK_EQ(1u, profile_fds.size()); CHECK(apk_fds != nullptr); CHECK_EQ(1u, apk_fds.size()); CHECK_EQ(1u, apk_fds->size()); } if (reference_profile_fd != -1) { AddArg("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get())); } } std::vector<std::string> args; args.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get())); for (const unique_fd& fd : profile_fds) { for (const unique_fd& fd : profile_fds) { args.push_back("--profile-file-fd=" + std::to_string(fd.get())); AddArg("--profile-file-fd=" + std::to_string(fd.get())); } } if (apk_fds != nullptr) { for (const unique_fd& fd : apk_fds) { for (const unique_fd& fd : *apk_fds) { AddArg("--apk-fd=" + std::to_string(fd.get())); args.push_back("--apk-fd=" + std::to_string(fd.get())); } } } std::vector<std::string> dex_location_args; for (const std::string& dex_location : dex_locations) { if (dex_locations != nullptr) { AddArg("--dex-location=" + dex_location); for (const std::string& dex_location : *dex_locations) { args.push_back("--dex-location=" + dex_location); } } } if (copy_and_update) { if (copy_and_update) { args.push_back("--copy-and-update-profile-key"); AddArg("--copy-and-update-profile-key"); } } // Do not add after dex2oat_flags, they should override others for debugging. // Do not add after dex2oat_flags, they should override others for debugging. PrepareArgs(profman_bin); ExecVWithArgs(profman_bin, args); PLOG(ERROR) << "execv(" << profman_bin << ") failed"; exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */ } } [[ noreturn ]] void SetupMerge(const std::vector<unique_fd>& profiles_fd, static void run_profman_merge(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd, const unique_fd& reference_profile_fd, const std::vector<unique_fd>* apk_fds = nullptr, const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(), const std::vector<std::string>* dex_locations = nullptr) { const std::vector<std::string>& dex_locations = std::vector<std::string>()) { run_profman(profiles_fd, reference_profile_fd, apk_fds, dex_locations, SetupArgs(profiles_fd, /*copy_and_update*/false); reference_profile_fd, apk_fds, dex_locations, /*copy_and_update=*/false); } } [[ noreturn ]] void SetupCopyAndUpdate(unique_fd&& profile_fd, static void run_profman_copy_and_update(unique_fd&& profile_fd, unique_fd&& reference_profile_fd, unique_fd&& reference_profile_fd, unique_fd&& apk_fd, unique_fd&& apk_fd, const std::string& dex_location) { const std::string& dex_location) { std::vector<unique_fd> profiles_fd; // The fds need to stay open longer than the scope of the function, so put them into a local profiles_fd.push_back(std::move(profile_fd)); // variable vector. std::vector<unique_fd> apk_fds; profiles_fd_.push_back(std::move(profile_fd)); apk_fds.push_back(std::move(apk_fd)); apk_fds_.push_back(std::move(apk_fd)); std::vector<std::string> dex_locations; reference_profile_fd_ = std::move(reference_profile_fd); dex_locations.push_back(dex_location); std::vector<std::string> dex_locations = {dex_location}; SetupArgs(profiles_fd_, reference_profile_fd_, apk_fds_, dex_locations, /*copy_and_update=*/true); } void SetupDump(const std::vector<unique_fd>& profiles_fd, const unique_fd& reference_profile_fd, const std::vector<std::string>& dex_locations, const std::vector<unique_fd>& apk_fds, const unique_fd& output_fd) { AddArg("--dump-only"); AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get())); SetupArgs(profiles_fd, reference_profile_fd, apk_fds, dex_locations, /*copy_and_update=*/false); } run_profman(profiles_fd, reference_profile_fd, &apk_fds, &dex_locations, void Exec() { /*copy_and_update*/true); ExecVHelper::Exec(DexoptReturnCodes::kProfmanExec); } } private: unique_fd reference_profile_fd_; std::vector<unique_fd> profiles_fd_; std::vector<unique_fd> apk_fds_; }; // Decides if profile guided compilation is needed or not based on existing profiles. // Decides if profile guided compilation is needed or not based on existing profiles. // The location is the package name for primary apks or the dex path for secondary dex files. // The location is the package name for primary apks or the dex path for secondary dex files. // Returns true if there is enough information in the current profiles that makes it // Returns true if there is enough information in the current profiles that makes it Loading @@ -697,11 +752,13 @@ static bool analyze_profiles(uid_t uid, const std::string& package_name, return false; return false; } } RunProfman profman_merge; profman_merge.SetupMerge(profiles_fd, reference_profile_fd); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(uid); drop_capabilities(uid); run_profman_merge(profiles_fd, reference_profile_fd); profman_merge.Exec(); } } /* parent */ /* parent */ int return_code = wait_child(pid); int return_code = wait_child(pid); Loading Loading @@ -774,35 +831,6 @@ bool analyze_primary_profiles(uid_t uid, const std::string& package_name, return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false); return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false); } } [[ noreturn ]] static void run_profman_dump(const std::vector<unique_fd>& profile_fds, const unique_fd& reference_profile_fd, const std::vector<std::string>& dex_locations, const std::vector<unique_fd>& apk_fds, const unique_fd& output_fd) { std::vector<std::string> profman_args; static const char* PROFMAN_BIN = "/system/bin/profman"; profman_args.push_back("--dump-only"); profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get())); if (reference_profile_fd != -1) { profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd.get())); } for (size_t i = 0; i < profile_fds.size(); i++) { profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get())); } for (const std::string& dex_location : dex_locations) { profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str())); } for (size_t i = 0; i < apk_fds.size(); i++) { profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get())); } ExecVWithArgs(PROFMAN_BIN, profman_args); PLOG(ERROR) << "execv(" << PROFMAN_BIN << ") failed"; exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */ } bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name, bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name, const std::string& code_path) { const std::string& code_path) { std::vector<unique_fd> profile_fds; std::vector<unique_fd> profile_fds; Loading Loading @@ -839,12 +867,13 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& p apk_fds.push_back(std::move(apk_fd)); apk_fds.push_back(std::move(apk_fd)); RunProfman profman_dump; profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds, output_fd); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(uid); drop_capabilities(uid); run_profman_dump(profile_fds, reference_profile_fd, dex_locations, profman_dump.Exec(); apk_fds, output_fd); } } /* parent */ /* parent */ int return_code = wait_child(pid); int return_code = wait_child(pid); Loading Loading @@ -1416,9 +1445,16 @@ void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter. // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter. // If this is for a profile guided compilation, profile_was_updated will tell whether or not // If this is for a profile guided compilation, profile_was_updated will tell whether or not // the profile has changed. // the profile has changed. static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oat_fd, class RunDexoptAnalyzer : public ExecVHelper { int zip_fd, const std::string& instruction_set, const std::string& compiler_filter, public: bool profile_was_updated, bool downgrade, RunDexoptAnalyzer(const std::string& dex_file, int vdex_fd, int oat_fd, int zip_fd, const std::string& instruction_set, const std::string& compiler_filter, bool profile_was_updated, bool downgrade, const char* class_loader_context) { const char* class_loader_context) { CHECK_GE(zip_fd, 0); CHECK_GE(zip_fd, 0); const char* dexoptanalyzer_bin = const char* dexoptanalyzer_bin = Loading @@ -1440,31 +1476,29 @@ static void exec_dexoptanalyzer(const std::string& dex_file, int vdex_fd, int oa } } // program name, dex file, isa, filter // program name, dex file, isa, filter std::vector<std::string> args = { AddArg(dex_file_arg); dex_file_arg, AddArg(isa_arg); isa_arg, AddArg(compiler_filter_arg); compiler_filter_arg, }; if (oat_fd >= 0) { if (oat_fd >= 0) { args.push_back(oat_fd_arg); AddArg(oat_fd_arg); } } if (vdex_fd >= 0) { if (vdex_fd >= 0) { args.push_back(vdex_fd_arg); AddArg(vdex_fd_arg); } } args.push_back(zip_fd_arg.c_str()); AddArg(zip_fd_arg.c_str()); if (profile_was_updated) { if (profile_was_updated) { args.push_back(assume_profile_changed); AddArg(assume_profile_changed); } } if (downgrade) { if (downgrade) { args.push_back(downgrade_flag); AddArg(downgrade_flag); } } if (class_loader_context != nullptr) { if (class_loader_context != nullptr) { args.push_back(class_loader_context_arg.c_str()); AddArg(class_loader_context_arg.c_str()); } } ExecVWithArgs(dexoptanalyzer_bin, args); PrepareArgs(dexoptanalyzer_bin); ALOGE("execv(%s) failed: %s\n", dexoptanalyzer_bin, strerror(errno)); } } }; // Prepares the oat dir for the secondary dex files. // Prepares the oat dir for the secondary dex files. static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid, static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid, Loading Loading @@ -1716,7 +1750,9 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char /*is_secondary_dex*/true); /*is_secondary_dex*/true); // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return. // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return. exec_dexoptanalyzer(dex_path, // Note that we do not do it before the fork since opening the files is required to happen // after forking. RunDexoptAnalyzer run_dexopt_analyzer(dex_path, vdex_file_fd.get(), vdex_file_fd.get(), oat_file_fd.get(), oat_file_fd.get(), zip_fd.get(), zip_fd.get(), Loading @@ -1724,8 +1760,7 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char compiler_filter, profile_was_updated, compiler_filter, profile_was_updated, downgrade, downgrade, class_loader_context); class_loader_context); PLOG(ERROR) << "Failed to exec dexoptanalyzer"; run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec); _exit(kSecondaryDexDexoptAnalyzerSkippedFailExec); } } /* parent */ /* parent */ Loading Loading @@ -1894,18 +1929,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---"; LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---"; pid_t pid = fork(); RunDex2Oat runner(input_fd.get(), if (pid == 0) { /* child -- drop privileges before continuing */ drop_capabilities(uid); SetDex2OatScheduling(boot_complete); if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) { PLOG(ERROR) << "flock(" << out_oat_path << ") failed"; _exit(DexoptReturnCodes::kFlock); } run_dex2oat(input_fd.get(), out_oat_fd.get(), out_oat_fd.get(), in_vdex_fd.get(), in_vdex_fd.get(), out_vdex_fd.get(), out_vdex_fd.get(), Loading @@ -1925,6 +1949,19 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins generate_compact_dex, generate_compact_dex, dex_metadata_fd.get(), dex_metadata_fd.get(), compilation_reason); compilation_reason); pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ drop_capabilities(uid); SetDex2OatScheduling(boot_complete); if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) { PLOG(ERROR) << "flock(" << out_oat_path << ") failed"; _exit(DexoptReturnCodes::kFlock); } runner.Exec(DexoptReturnCodes::kDex2oatExec); } else { } else { int res = wait_child(pid); int res = wait_child(pid); if (res == 0) { if (res == 0) { Loading Loading @@ -2488,11 +2525,13 @@ static bool create_app_profile_snapshot(int32_t app_id, return false; return false; } } RunProfman args; args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(app_shared_gid); drop_capabilities(app_shared_gid); run_profman_merge(profiles_fd, snapshot_fd, &apk_fds, &dex_locations); args.Exec(); } } /* parent */ /* parent */ Loading Loading @@ -2572,6 +2611,8 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, profiles_fd.push_back(std::move(fd)); profiles_fd.push_back(std::move(fd)); } } } } RunProfman args; args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ Loading @@ -2579,7 +2620,7 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, // The introduction of new access flags into boot jars causes them to // The introduction of new access flags into boot jars causes them to // fail dex file verification. // fail dex file verification. run_profman_merge(profiles_fd, snapshot_fd, &apk_fds, &dex_locations); args.Exec(); } } /* parent */ /* parent */ Loading Loading @@ -2633,6 +2674,11 @@ bool prepare_app_profile(const std::string& package_name, return false; return false; } } RunProfman args; args.SetupCopyAndUpdate(std::move(dex_metadata_fd), std::move(ref_profile_fd), std::move(apk_fd), code_path); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ Loading @@ -2640,10 +2686,7 @@ bool prepare_app_profile(const std::string& package_name, drop_capabilities(app_shared_gid); drop_capabilities(app_shared_gid); // The copy and update takes ownership over the fds. // The copy and update takes ownership over the fds. run_profman_copy_and_update(std::move(dex_metadata_fd), args.Exec(); std::move(ref_profile_fd), std::move(apk_fd), code_path); } } /* parent */ /* parent */ Loading