Loading cmds/installd/InstalldNativeService.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -1963,6 +1963,20 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, return res ? ok() : error(); } binder::Status InstalldNativeService::reconcileSecondaryDexFile( const std::string& dexPath, const std::string& packageName, int32_t uid, const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); bool result = android::installd::reconcile_secondary_dex_file( dexPath, packageName, uid, isas, volumeUuid, storage_flag, _aidl_return); return result ? ok() : error(); } binder::Status InstalldNativeService::invalidateMounts() { ENFORCE_UID(AID_SYSTEM); std::lock_guard<std::recursive_mutex> lock(mLock); Loading cmds/installd/InstalldNativeService.h +3 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,9 @@ public: const std::string& outputPath); binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::string& outputPath); binder::Status reconcileSecondaryDexFile(const std::string& dexPath, const std::string& packageName, int32_t uid, const std::vector<std::string>& isa, const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return); binder::Status invalidateMounts(); Loading cmds/installd/binder/android/os/IInstalld.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -72,5 +72,9 @@ interface IInstalld { void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet, @utf8InCpp String outputPath); boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName, int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid, int storage_flag); void invalidateMounts(); } cmds/installd/dexopt.cpp +142 −31 Original line number Diff line number Diff line Loading @@ -1245,12 +1245,12 @@ static void exec_dexoptanalyzer(const char* dex_file, const char* instruction_se } // Prepares the oat dir for the secondary dex files. static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid, static bool prepare_secondary_dex_oat_dir(const char* dex_path, int uid, const char* instruction_set, std::string* oat_dir_out) { std::string apk_path_str(apk_path); std::string apk_path_str(dex_path); unsigned long dirIndex = apk_path_str.rfind('/'); if (dirIndex == std::string::npos) { LOG(WARNING) << "Unexpected dir structure for secondary dex " << apk_path; LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path; return false; } std::string apk_dir = apk_path_str.substr(0, dirIndex); Loading @@ -1266,7 +1266,7 @@ static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid, // Create oat file output directory. if (prepare_app_cache_dir(apk_dir, "oat", 02711, uid, cache_gid) != 0) { LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << apk_path; LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path; return false; } Loading @@ -1276,7 +1276,7 @@ static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid, // Create oat/isa output directory. if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) { LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << apk_path; LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path; return false; } Loading @@ -1288,7 +1288,7 @@ static int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200; // Verifies the result of dexoptanalyzer executed for the apk_path. // If the result is valid returns true and sets dexopt_needed_out to a valid value. // Returns false for errors or unexpected result values. static bool process_dexoptanalyzer_result(const char* apk_path, int result, static bool process_dexoptanalyzer_result(const char* dex_path, int result, int* dexopt_needed_out) { // The result values are defined in dexoptanalyzer. switch (result) { Loading @@ -1305,22 +1305,23 @@ static bool process_dexoptanalyzer_result(const char* apk_path, int result, case 2: // dex2oat_for_bootimage_oat case 3: // dex2oat_for_filter_oat case 4: // dex2oat_for_relocation_oat LOG(ERROR) << "Expected odex file status for secondary dex " << apk_path LOG(ERROR) << "Dexoptnalyzer return the status of an oat file." << " Expected odex file status for secondary dex " << dex_path << " : dexoptanalyzer result=" << result; return false; default: LOG(ERROR) << "Unexpected result for dexoptanalyzer " << apk_path LOG(ERROR) << "Unexpected result for dexoptanalyzer " << dex_path << " exec_dexoptanalyzer result=" << result; return false; } } // Processes the apk_path as a secondary dex files and return true if the path dex file should // Processes the dex_path as a secondary dex files and return true if the path dex file should // be compiled. Returns false for errors (logged) or true if the secondary dex path was process // successfully. // When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded // code and aot_dir_out is assigned the oat dir path where the oat file should be stored. static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgname, static bool process_secondary_dex_dexopt(const char* dex_path, const char* pkgname, int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set, const char* compiler_filter, int* dexopt_needed_out, std::string* aot_dir_out) { int storage_flag; Loading @@ -1338,25 +1339,25 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna return false; } if (!validate_secondary_dex_path(pkgname, apk_path, volume_uuid, uid, storage_flag)) { LOG(ERROR) << "Could not validate secondary dex path " << apk_path; if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) { LOG(ERROR) << "Could not validate secondary dex path " << dex_path; return false; } // Check if the path exist. If not, there's nothing to do. if (access(apk_path, F_OK) != 0) { if (access(dex_path, F_OK) != 0) { if (errno == ENOENT) { // Secondary dex files might be deleted any time by the app. // Nothing to do if that's the case ALOGV("Secondary dex does not exist %s", apk_path); ALOGV("Secondary dex does not exist %s", dex_path); return NO_DEXOPT_NEEDED; } else { PLOG(ERROR) << "Could not access secondary dex " << apk_path; PLOG(ERROR) << "Could not access secondary dex " << dex_path; } } // Prepare the oat directories. if (!prepare_secondary_dex_oat_dir(apk_path, uid, instruction_set, aot_dir_out)) { if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, aot_dir_out)) { return false; } Loading @@ -1365,7 +1366,7 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna // child -- drop privileges before continuing. drop_capabilities(uid); // Run dexoptanalyzer to get dexopt_needed code. exec_dexoptanalyzer(apk_path, instruction_set, compiler_filter); exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter); exit(DEXOPTANALYZER_BIN_EXEC_ERROR); } Loading @@ -1373,11 +1374,11 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna int result = wait_child(pid); if (!WIFEXITED(result)) { LOG(ERROR) << "dexoptanalyzer failed for path " << apk_path << ": " << result; LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result; return false; } result = WEXITSTATUS(result); bool success = process_dexoptanalyzer_result(apk_path, result, dexopt_needed_out); bool success = process_dexoptanalyzer_result(dex_path, result, dexopt_needed_out); // Run dexopt only if needed or forced. // Note that dexoptanalyzer is executed even if force compilation is enabled. // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result) Loading @@ -1390,7 +1391,7 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna return success; } int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set, int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, const char* volume_uuid, const char* shared_libraries) { CHECK(pkgname != nullptr); Loading @@ -1409,7 +1410,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins // Check if we're dealing with a secondary dex file and if we need to compile it. std::string oat_dir_str; if (is_secondary_dex) { if (process_secondary_dex_dexopt(apk_path, pkgname, dexopt_flags, volume_uuid, uid, if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid, instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str)) { oat_dir = oat_dir_str.c_str(); if (dexopt_needed == NO_DEXOPT_NEEDED) { Loading @@ -1419,22 +1420,23 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins return -1; // We had an error, logged in the process method. } } else { // Verify that secondary dex files are not set. // Currently these flags are only use for secondary dex files. // Verify that they are not set for primary apks. CHECK((dexopt_flags & DEXOPT_FORCE) == 0); CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0); CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0); } // Open the input file. base::unique_fd input_fd(open(apk_path, O_RDONLY, 0)); base::unique_fd input_fd(open(dex_path, O_RDONLY, 0)); if (input_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", apk_path); ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path); return -1; } // Create the output OAT file. char out_oat_path[PKG_PATH_MAX]; Dex2oatFileWrapper out_oat_fd = open_oat_out_file(apk_path, oat_dir, is_public, uid, Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid, instruction_set, is_secondary_dex, out_oat_path); if (out_oat_fd.get() < 0) { return -1; Loading @@ -1443,7 +1445,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins // Open vdex files. Dex2oatFileWrapper in_vdex_fd; Dex2oatFileWrapper out_vdex_fd; if (!open_vdex_files(apk_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid, if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid, &in_vdex_fd, &out_vdex_fd)) { return -1; } Loading @@ -1459,7 +1461,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(pkgname, profile_guided, is_public, uid, is_secondary_dex); ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path); ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path); pid_t pid = fork(); if (pid == 0) { Loading @@ -1473,7 +1475,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins } // Pass dex2oat the relative path to the input file. const char *input_file_name = get_location_from_path(apk_path); const char *input_file_name = get_location_from_path(dex_path); run_dex2oat(input_fd.get(), out_oat_fd.get(), in_vdex_fd.get(), Loading @@ -1493,14 +1495,14 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins } else { int res = wait_child(pid); if (res == 0) { ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path); ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path); } else { ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", apk_path, res); ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res); return -1; } } update_out_oat_access_times(apk_path, out_oat_path); update_out_oat_access_times(dex_path, out_oat_path); // We've been successful, don't delete output. out_oat_fd.SetCleanup(false); Loading @@ -1511,6 +1513,115 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins return 0; } // Try to remove the given directory. Log an error if the directory exists // and is empty but could not be removed. static bool rmdir_if_empty(const char* dir) { if (rmdir(dir) == 0) { return true; } if (errno == ENOENT || errno == ENOTEMPTY) { return true; } PLOG(ERROR) << "Failed to remove dir: " << dir; return false; } // Try to unlink the given file. Log an error if the file exists and could not // be unlinked. static bool unlink_if_exists(const std::string& file) { if (unlink(file.c_str()) == 0) { return true; } if (errno == ENOENT) { return true; } PLOG(ERROR) << "Could not unlink: " << file; return false; } // Create the oat file structure for the secondary dex 'dex_path' and assign // the individual path component to the 'out_' parameters. static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa, /*out*/char* out_oat_dir, /*out*/char* out_oat_isa_dir, /*out*/char* out_oat_path) { size_t dirIndex = dex_path.rfind('/'); if (dirIndex == std::string::npos) { LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path; return false; } // TODO(calin): we have similar computations in at lest 3 other places // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by // use string append. std::string apk_dir = dex_path.substr(0, dirIndex); snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str()); snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str()); if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir, /*is_secondary_dex*/ true, out_oat_path)) { LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path; return false; } return true; } // Reconcile the secondary dex 'dex_path' and its generated oat files. // Return true if all the parameters are valid and the secondary dex file was // processed successfully (i.e. the dex_path either exists, or if not, its corresponding // oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists // will be true if the secondary dex file still exists. If the secondary dex file does not exist, // the method cleans up any previously generated compiler artifacts (oat, vdex, art). // Return false if there were errors during processing. In this case // out_secondary_dex_exists will be set to false. bool reconcile_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid, const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volume_uuid, int storage_flag, /*out*/bool* out_secondary_dex_exists) { // Set out to false to start with, just in case we have validation errors. *out_secondary_dex_exists = false; if (isas.size() == 0) { LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector"; return false; } const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str(); if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr, uid, storage_flag)) { LOG(ERROR) << "Could not validate secondary dex path " << dex_path; return false; } if (access(dex_path.c_str(), F_OK) == 0) { // The path exists, nothing to do. The odex files (if any) will be left untouched. *out_secondary_dex_exists = true; return true; } else if (errno != ENOENT) { PLOG(ERROR) << "Failed to check access to secondary dex " << dex_path; return false; } // The secondary dex does not exist anymore. Clear any generated files. char oat_path[PKG_PATH_MAX]; char oat_dir[PKG_PATH_MAX]; char oat_isa_dir[PKG_PATH_MAX]; bool result = true; for (size_t i = 0; i < isas.size(); i++) { if (!create_secondary_dex_oat_layout(dex_path, isas[i], oat_dir, oat_isa_dir, oat_path)) { LOG(ERROR) << "Could not create secondary odex layout: " << dex_path; result = false; continue; } result = unlink_if_exists(oat_path) && result; result = unlink_if_exists(create_vdex_filename(oat_path)) && result; result = unlink_if_exists(create_image_filename(oat_path)) && result; // Try removing the directories as well, they might be empty. result = rmdir_if_empty(oat_isa_dir) && result; result = rmdir_if_empty(oat_dir) && result; } return result; } // Helper for move_ab, so that we can have common failure-case cleanup. static bool unlink_and_rename(const char* from, const char* to) { // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise, Loading cmds/installd/dexopt.h +5 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,11 @@ bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths); bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path); bool reconcile_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid, const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid, int storage_flag, /*out*/bool* out_secondary_dex_exists); int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, const char* volume_uuid, const char* shared_libraries); Loading Loading
cmds/installd/InstalldNativeService.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -1963,6 +1963,20 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, return res ? ok() : error(); } binder::Status InstalldNativeService::reconcileSecondaryDexFile( const std::string& dexPath, const std::string& packageName, int32_t uid, const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); bool result = android::installd::reconcile_secondary_dex_file( dexPath, packageName, uid, isas, volumeUuid, storage_flag, _aidl_return); return result ? ok() : error(); } binder::Status InstalldNativeService::invalidateMounts() { ENFORCE_UID(AID_SYSTEM); std::lock_guard<std::recursive_mutex> lock(mLock); Loading
cmds/installd/InstalldNativeService.h +3 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,9 @@ public: const std::string& outputPath); binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::string& outputPath); binder::Status reconcileSecondaryDexFile(const std::string& dexPath, const std::string& packageName, int32_t uid, const std::vector<std::string>& isa, const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return); binder::Status invalidateMounts(); Loading
cmds/installd/binder/android/os/IInstalld.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -72,5 +72,9 @@ interface IInstalld { void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet, @utf8InCpp String outputPath); boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName, int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid, int storage_flag); void invalidateMounts(); }
cmds/installd/dexopt.cpp +142 −31 Original line number Diff line number Diff line Loading @@ -1245,12 +1245,12 @@ static void exec_dexoptanalyzer(const char* dex_file, const char* instruction_se } // Prepares the oat dir for the secondary dex files. static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid, static bool prepare_secondary_dex_oat_dir(const char* dex_path, int uid, const char* instruction_set, std::string* oat_dir_out) { std::string apk_path_str(apk_path); std::string apk_path_str(dex_path); unsigned long dirIndex = apk_path_str.rfind('/'); if (dirIndex == std::string::npos) { LOG(WARNING) << "Unexpected dir structure for secondary dex " << apk_path; LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path; return false; } std::string apk_dir = apk_path_str.substr(0, dirIndex); Loading @@ -1266,7 +1266,7 @@ static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid, // Create oat file output directory. if (prepare_app_cache_dir(apk_dir, "oat", 02711, uid, cache_gid) != 0) { LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << apk_path; LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path; return false; } Loading @@ -1276,7 +1276,7 @@ static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid, // Create oat/isa output directory. if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) { LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << apk_path; LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path; return false; } Loading @@ -1288,7 +1288,7 @@ static int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200; // Verifies the result of dexoptanalyzer executed for the apk_path. // If the result is valid returns true and sets dexopt_needed_out to a valid value. // Returns false for errors or unexpected result values. static bool process_dexoptanalyzer_result(const char* apk_path, int result, static bool process_dexoptanalyzer_result(const char* dex_path, int result, int* dexopt_needed_out) { // The result values are defined in dexoptanalyzer. switch (result) { Loading @@ -1305,22 +1305,23 @@ static bool process_dexoptanalyzer_result(const char* apk_path, int result, case 2: // dex2oat_for_bootimage_oat case 3: // dex2oat_for_filter_oat case 4: // dex2oat_for_relocation_oat LOG(ERROR) << "Expected odex file status for secondary dex " << apk_path LOG(ERROR) << "Dexoptnalyzer return the status of an oat file." << " Expected odex file status for secondary dex " << dex_path << " : dexoptanalyzer result=" << result; return false; default: LOG(ERROR) << "Unexpected result for dexoptanalyzer " << apk_path LOG(ERROR) << "Unexpected result for dexoptanalyzer " << dex_path << " exec_dexoptanalyzer result=" << result; return false; } } // Processes the apk_path as a secondary dex files and return true if the path dex file should // Processes the dex_path as a secondary dex files and return true if the path dex file should // be compiled. Returns false for errors (logged) or true if the secondary dex path was process // successfully. // When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded // code and aot_dir_out is assigned the oat dir path where the oat file should be stored. static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgname, static bool process_secondary_dex_dexopt(const char* dex_path, const char* pkgname, int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set, const char* compiler_filter, int* dexopt_needed_out, std::string* aot_dir_out) { int storage_flag; Loading @@ -1338,25 +1339,25 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna return false; } if (!validate_secondary_dex_path(pkgname, apk_path, volume_uuid, uid, storage_flag)) { LOG(ERROR) << "Could not validate secondary dex path " << apk_path; if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) { LOG(ERROR) << "Could not validate secondary dex path " << dex_path; return false; } // Check if the path exist. If not, there's nothing to do. if (access(apk_path, F_OK) != 0) { if (access(dex_path, F_OK) != 0) { if (errno == ENOENT) { // Secondary dex files might be deleted any time by the app. // Nothing to do if that's the case ALOGV("Secondary dex does not exist %s", apk_path); ALOGV("Secondary dex does not exist %s", dex_path); return NO_DEXOPT_NEEDED; } else { PLOG(ERROR) << "Could not access secondary dex " << apk_path; PLOG(ERROR) << "Could not access secondary dex " << dex_path; } } // Prepare the oat directories. if (!prepare_secondary_dex_oat_dir(apk_path, uid, instruction_set, aot_dir_out)) { if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, aot_dir_out)) { return false; } Loading @@ -1365,7 +1366,7 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna // child -- drop privileges before continuing. drop_capabilities(uid); // Run dexoptanalyzer to get dexopt_needed code. exec_dexoptanalyzer(apk_path, instruction_set, compiler_filter); exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter); exit(DEXOPTANALYZER_BIN_EXEC_ERROR); } Loading @@ -1373,11 +1374,11 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna int result = wait_child(pid); if (!WIFEXITED(result)) { LOG(ERROR) << "dexoptanalyzer failed for path " << apk_path << ": " << result; LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result; return false; } result = WEXITSTATUS(result); bool success = process_dexoptanalyzer_result(apk_path, result, dexopt_needed_out); bool success = process_dexoptanalyzer_result(dex_path, result, dexopt_needed_out); // Run dexopt only if needed or forced. // Note that dexoptanalyzer is executed even if force compilation is enabled. // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result) Loading @@ -1390,7 +1391,7 @@ static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgna return success; } int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set, int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, const char* volume_uuid, const char* shared_libraries) { CHECK(pkgname != nullptr); Loading @@ -1409,7 +1410,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins // Check if we're dealing with a secondary dex file and if we need to compile it. std::string oat_dir_str; if (is_secondary_dex) { if (process_secondary_dex_dexopt(apk_path, pkgname, dexopt_flags, volume_uuid, uid, if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid, instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str)) { oat_dir = oat_dir_str.c_str(); if (dexopt_needed == NO_DEXOPT_NEEDED) { Loading @@ -1419,22 +1420,23 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins return -1; // We had an error, logged in the process method. } } else { // Verify that secondary dex files are not set. // Currently these flags are only use for secondary dex files. // Verify that they are not set for primary apks. CHECK((dexopt_flags & DEXOPT_FORCE) == 0); CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0); CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0); } // Open the input file. base::unique_fd input_fd(open(apk_path, O_RDONLY, 0)); base::unique_fd input_fd(open(dex_path, O_RDONLY, 0)); if (input_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", apk_path); ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path); return -1; } // Create the output OAT file. char out_oat_path[PKG_PATH_MAX]; Dex2oatFileWrapper out_oat_fd = open_oat_out_file(apk_path, oat_dir, is_public, uid, Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid, instruction_set, is_secondary_dex, out_oat_path); if (out_oat_fd.get() < 0) { return -1; Loading @@ -1443,7 +1445,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins // Open vdex files. Dex2oatFileWrapper in_vdex_fd; Dex2oatFileWrapper out_vdex_fd; if (!open_vdex_files(apk_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid, if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid, &in_vdex_fd, &out_vdex_fd)) { return -1; } Loading @@ -1459,7 +1461,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(pkgname, profile_guided, is_public, uid, is_secondary_dex); ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path); ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path); pid_t pid = fork(); if (pid == 0) { Loading @@ -1473,7 +1475,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins } // Pass dex2oat the relative path to the input file. const char *input_file_name = get_location_from_path(apk_path); const char *input_file_name = get_location_from_path(dex_path); run_dex2oat(input_fd.get(), out_oat_fd.get(), in_vdex_fd.get(), Loading @@ -1493,14 +1495,14 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins } else { int res = wait_child(pid); if (res == 0) { ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path); ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path); } else { ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", apk_path, res); ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res); return -1; } } update_out_oat_access_times(apk_path, out_oat_path); update_out_oat_access_times(dex_path, out_oat_path); // We've been successful, don't delete output. out_oat_fd.SetCleanup(false); Loading @@ -1511,6 +1513,115 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins return 0; } // Try to remove the given directory. Log an error if the directory exists // and is empty but could not be removed. static bool rmdir_if_empty(const char* dir) { if (rmdir(dir) == 0) { return true; } if (errno == ENOENT || errno == ENOTEMPTY) { return true; } PLOG(ERROR) << "Failed to remove dir: " << dir; return false; } // Try to unlink the given file. Log an error if the file exists and could not // be unlinked. static bool unlink_if_exists(const std::string& file) { if (unlink(file.c_str()) == 0) { return true; } if (errno == ENOENT) { return true; } PLOG(ERROR) << "Could not unlink: " << file; return false; } // Create the oat file structure for the secondary dex 'dex_path' and assign // the individual path component to the 'out_' parameters. static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa, /*out*/char* out_oat_dir, /*out*/char* out_oat_isa_dir, /*out*/char* out_oat_path) { size_t dirIndex = dex_path.rfind('/'); if (dirIndex == std::string::npos) { LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path; return false; } // TODO(calin): we have similar computations in at lest 3 other places // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by // use string append. std::string apk_dir = dex_path.substr(0, dirIndex); snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str()); snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str()); if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir, /*is_secondary_dex*/ true, out_oat_path)) { LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path; return false; } return true; } // Reconcile the secondary dex 'dex_path' and its generated oat files. // Return true if all the parameters are valid and the secondary dex file was // processed successfully (i.e. the dex_path either exists, or if not, its corresponding // oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists // will be true if the secondary dex file still exists. If the secondary dex file does not exist, // the method cleans up any previously generated compiler artifacts (oat, vdex, art). // Return false if there were errors during processing. In this case // out_secondary_dex_exists will be set to false. bool reconcile_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid, const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volume_uuid, int storage_flag, /*out*/bool* out_secondary_dex_exists) { // Set out to false to start with, just in case we have validation errors. *out_secondary_dex_exists = false; if (isas.size() == 0) { LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector"; return false; } const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str(); if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr, uid, storage_flag)) { LOG(ERROR) << "Could not validate secondary dex path " << dex_path; return false; } if (access(dex_path.c_str(), F_OK) == 0) { // The path exists, nothing to do. The odex files (if any) will be left untouched. *out_secondary_dex_exists = true; return true; } else if (errno != ENOENT) { PLOG(ERROR) << "Failed to check access to secondary dex " << dex_path; return false; } // The secondary dex does not exist anymore. Clear any generated files. char oat_path[PKG_PATH_MAX]; char oat_dir[PKG_PATH_MAX]; char oat_isa_dir[PKG_PATH_MAX]; bool result = true; for (size_t i = 0; i < isas.size(); i++) { if (!create_secondary_dex_oat_layout(dex_path, isas[i], oat_dir, oat_isa_dir, oat_path)) { LOG(ERROR) << "Could not create secondary odex layout: " << dex_path; result = false; continue; } result = unlink_if_exists(oat_path) && result; result = unlink_if_exists(create_vdex_filename(oat_path)) && result; result = unlink_if_exists(create_image_filename(oat_path)) && result; // Try removing the directories as well, they might be empty. result = rmdir_if_empty(oat_isa_dir) && result; result = rmdir_if_empty(oat_dir) && result; } return result; } // Helper for move_ab, so that we can have common failure-case cleanup. static bool unlink_and_rename(const char* from, const char* to) { // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise, Loading
cmds/installd/dexopt.h +5 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,11 @@ bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths); bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path); bool reconcile_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid, const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid, int storage_flag, /*out*/bool* out_secondary_dex_exists); int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, const char* volume_uuid, const char* shared_libraries); Loading