Loading cmds/installd/InstalldNativeService.cpp +19 −12 Original line number Diff line number Diff line Loading @@ -107,6 +107,10 @@ namespace { constexpr const char* kDump = "android.permission.DUMP"; // TODO(calin): We can stop hardcoding this here once the PM passes the profile // name for all profile related operations. constexpr const char* kPrimaryProfileName = "primary.prof"; static binder::Status ok() { return binder::Status::ok(); } Loading Loading @@ -384,8 +388,9 @@ static bool prepare_app_profile_dir(const std::string& packageName, int32_t appI PLOG(ERROR) << "Failed to prepare " << profile_dir; return false; } const std::string profile_file = create_current_profile_path(userId, packageName, /*is_secondary_dex*/false); kPrimaryProfileName, /*is_secondary_dex*/false); // read-write only for the app user. if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << profile_file; Loading Loading @@ -546,10 +551,10 @@ binder::Status InstalldNativeService::clearAppProfiles(const std::string& packag std::lock_guard<std::recursive_mutex> lock(mLock); binder::Status res = ok(); if (!clear_primary_reference_profile(packageName)) { if (!clear_primary_reference_profile(packageName, kPrimaryProfileName)) { res = error("Failed to clear reference profile for " + packageName); } if (!clear_primary_current_profiles(packageName)) { if (!clear_primary_current_profiles(packageName, kPrimaryProfileName)) { res = error("Failed to clear current profiles for " + packageName); } return res; Loading Loading @@ -600,7 +605,7 @@ binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::st } } if (!only_cache) { if (!clear_primary_current_profile(packageName, userId)) { if (!clear_primary_current_profile(packageName, kPrimaryProfileName, userId)) { res = error("Failed to clear current profile for " + packageName); } } Loading Loading @@ -1869,7 +1874,8 @@ binder::Status InstalldNativeService::copySystemProfile(const std::string& syste ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName); *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName, kPrimaryProfileName); return ok(); } Loading @@ -1880,29 +1886,29 @@ binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::stri CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); *_aidl_return = analyze_primary_profiles(uid, packageName); *_aidl_return = analyze_primary_profiles(uid, packageName, kPrimaryProfileName); return ok(); } binder::Status InstalldNativeService::createProfileSnapshot(int32_t appId, const std::string& packageName, const std::string& codePath, bool* _aidl_return) { const std::string& packageName, const std::string& profileName, bool* _aidl_return) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); *_aidl_return = create_profile_snapshot(appId, packageName, codePath); *_aidl_return = create_profile_snapshot(appId, packageName, profileName); return ok(); } binder::Status InstalldNativeService::destroyProfileSnapshot(const std::string& packageName, const std::string& codePath) { const std::string& profileName) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); std::string snapshot = create_snapshot_profile_path(packageName, codePath); std::string snapshot = create_snapshot_profile_path(packageName, profileName); if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) { return error("Failed to destroy profile snapshot for " + packageName + ":" + codePath); return error("Failed to destroy profile snapshot for " + packageName + ":" + profileName); } return ok(); } Loading @@ -1928,9 +1934,10 @@ binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t const char* volume_uuid = uuid ? uuid->c_str() : nullptr; const char* class_loader_context = classLoaderContext ? classLoaderContext->c_str() : nullptr; const char* se_info = seInfo ? seInfo->c_str() : nullptr; int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded, oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info, downgrade, targetSdkVersion); downgrade, targetSdkVersion, kPrimaryProfileName); return res ? error(res, "Failed to dexopt") : ok(); } Loading cmds/installd/dexopt.cpp +73 −56 Original line number Diff line number Diff line Loading @@ -137,37 +137,43 @@ static bool clear_profile(const std::string& profile) { } // Clear the reference profile for the given location. // The location is the package name for primary apks or the dex path for secondary dex files. static bool clear_reference_profile(const std::string& location, bool is_secondary_dex) { return clear_profile(create_reference_profile_path(location, is_secondary_dex)); // The location is the profile name for primary apks or the dex path for secondary dex files. static bool clear_reference_profile(const std::string& package_name, const std::string& location, bool is_secondary_dex) { return clear_profile(create_reference_profile_path(package_name, location, is_secondary_dex)); } // Clear the reference profile for the given location. // The location is the package name for primary apks or the dex path for secondary dex files. static bool clear_current_profile(const std::string& pkgname, userid_t user, bool is_secondary_dex) { return clear_profile(create_current_profile_path(user, pkgname, is_secondary_dex)); // The location is the profile name for primary apks or the dex path for secondary dex files. static bool clear_current_profile(const std::string& package_name, const std::string& location, userid_t user, bool is_secondary_dex) { return clear_profile(create_current_profile_path(user, package_name, location, is_secondary_dex)); } // Clear the reference profile for the primary apk of the given package. bool clear_primary_reference_profile(const std::string& pkgname) { return clear_reference_profile(pkgname, /*is_secondary_dex*/false); // The location is the profile name for primary apks or the dex path for secondary dex files. bool clear_primary_reference_profile(const std::string& package_name, const std::string& location) { return clear_reference_profile(package_name, location, /*is_secondary_dex*/false); } // Clear all current profile for the primary apk of the given package. bool clear_primary_current_profiles(const std::string& pkgname) { // The location is the profile name for primary apks or the dex path for secondary dex files. bool clear_primary_current_profiles(const std::string& package_name, const std::string& location) { bool success = true; // For secondary dex files, we don't really need the user but we use it for sanity checks. std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); for (auto user : users) { success &= clear_current_profile(pkgname, user, /*is_secondary_dex*/false); success &= clear_current_profile(package_name, location, user, /*is_secondary_dex*/false); } return success; } // Clear the current profile for the primary apk of the given package and user. bool clear_primary_current_profile(const std::string& pkgname, userid_t user) { return clear_current_profile(pkgname, user, /*is_secondary_dex*/false); bool clear_primary_current_profile(const std::string& package_name, const std::string& location, userid_t user) { return clear_current_profile(package_name, location, user, /*is_secondary_dex*/false); } static int split_count(const char *str) Loading Loading @@ -638,29 +644,31 @@ static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t fla return fd; } static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location, bool is_secondary_dex) { std::string profile = create_current_profile_path(user, location, is_secondary_dex); static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& package_name, const std::string& location, bool is_secondary_dex) { std::string profile = create_current_profile_path(user, package_name, location, is_secondary_dex); return open_profile(uid, profile, O_RDONLY); } static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write, bool is_secondary_dex) { std::string profile = create_reference_profile_path(location, is_secondary_dex); static unique_fd open_reference_profile(uid_t uid, const std::string& package_name, const std::string& location, bool read_write, bool is_secondary_dex) { std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex); return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY); } static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name, const std::string& code_path) { std::string profile = create_snapshot_profile_path(package_name, code_path); const std::string& location) { std::string profile = create_snapshot_profile_path(package_name, location); return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC); } static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex, static void open_profile_files(uid_t uid, const std::string& package_name, const std::string& location, bool is_secondary_dex, /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) { // Open the reference profile in read-write mode as profman might need to save the merge. *reference_profile_fd = open_reference_profile(uid, location, /*read_write*/ true, is_secondary_dex); *reference_profile_fd = open_reference_profile(uid, package_name, location, /*read_write*/ true, is_secondary_dex); // For secondary dex files, we don't really need the user but we use it for sanity checks. // Note: the user owning the dex file should be the current user. Loading @@ -671,7 +679,8 @@ static void open_profile_files(uid_t uid, const std::string& location, bool is_s users = get_known_users(/*volume_uuid*/ nullptr); } for (auto user : users) { unique_fd profile_fd = open_current_profile(uid, user, location, is_secondary_dex); unique_fd profile_fd = open_current_profile(uid, user, package_name, location, is_secondary_dex); // Add to the lists only if both fds are valid. if (profile_fd.get() >= 0) { profiles_fd->push_back(std::move(profile_fd)); Loading Loading @@ -742,10 +751,12 @@ static void run_profman_merge(const std::vector<unique_fd>& profiles_fd, // worth to recompile the given location. // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). static bool analyze_profiles(uid_t uid, const std::string& location, bool is_secondary_dex) { static bool analyze_profiles(uid_t uid, const std::string& package_name, const std::string& location, bool is_secondary_dex) { std::vector<unique_fd> profiles_fd; unique_fd reference_profile_fd; open_profile_files(uid, location, is_secondary_dex, &profiles_fd, &reference_profile_fd); open_profile_files(uid, package_name, location, is_secondary_dex, &profiles_fd, &reference_profile_fd); if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) { // Skip profile guided compilation because no profiles were found. // Or if the reference profile info couldn't be opened. Loading Loading @@ -807,13 +818,14 @@ static bool analyze_profiles(uid_t uid, const std::string& location, bool is_sec if (should_clear_current_profiles) { if (is_secondary_dex) { // For secondary dex files, the owning user is the current user. clear_current_profile(location, multiuser_get_user_id(uid), is_secondary_dex); clear_current_profile(package_name, location, multiuser_get_user_id(uid), is_secondary_dex); } else { clear_primary_current_profiles(location); clear_primary_current_profiles(package_name, location); } } if (should_clear_reference_profile) { clear_reference_profile(location, is_secondary_dex); clear_reference_profile(package_name, location, is_secondary_dex); } return need_to_compile; } Loading @@ -824,8 +836,9 @@ static bool analyze_profiles(uid_t uid, const std::string& location, bool is_sec // worth to recompile the package. // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). bool analyze_primary_profiles(uid_t uid, const std::string& pkgname) { return analyze_profiles(uid, pkgname, /*is_secondary_dex*/false); bool analyze_primary_profiles(uid_t uid, const std::string& package_name, const std::string& profile_name) { return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false); } static void run_profman_dump(const std::vector<unique_fd>& profile_fds, Loading Loading @@ -868,7 +881,8 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat unique_fd reference_profile_fd; std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str()); open_profile_files(uid, pkgname, /*is_secondary_dex*/false, // TODO(calin): get the profile name as a parameter. open_profile_files(uid, pkgname, "primary.prof", /*is_secondary_dex*/false, &profile_fds, &reference_profile_fd); const bool has_reference_profile = (reference_profile_fd.get() != -1); Loading Loading @@ -918,10 +932,11 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat } bool copy_system_profile(const std::string& system_profile, uid_t packageUid, const std::string& data_profile_location) { uid_t packageUid, const std::string& package_name, const std::string& profile_name) { unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)); unique_fd out_fd(open_reference_profile(packageUid, data_profile_location, package_name, profile_name, /*read_write*/ true, /*secondary*/ false)); if (in_fd.get() < 0) { Loading @@ -929,7 +944,7 @@ bool copy_system_profile(const std::string& system_profile, return false; } if (out_fd.get() < 0) { PLOG(WARNING) << "Could not open profile " << data_profile_location; PLOG(WARNING) << "Could not open profile " << package_name; return false; } Loading @@ -942,7 +957,7 @@ bool copy_system_profile(const std::string& system_profile, if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) { if (errno != EWOULDBLOCK) { PLOG(WARNING) << "Error locking profile " << data_profile_location; PLOG(WARNING) << "Error locking profile " << package_name; } // This implies that the app owning this profile is running // (and has acquired the lock). Loading @@ -950,13 +965,13 @@ bool copy_system_profile(const std::string& system_profile, // The app never acquires the lock for the reference profiles of primary apks. // Only dex2oat from installd will do that. Since installd is single threaded // we should not see this case. Nevertheless be prepared for it. PLOG(WARNING) << "Failed to flock " << data_profile_location; PLOG(WARNING) << "Failed to flock " << package_name; return false; } bool truncated = ftruncate(out_fd.get(), 0) == 0; if (!truncated) { PLOG(WARNING) << "Could not truncate " << data_profile_location; PLOG(WARNING) << "Could not truncate " << package_name; } // Copy over data. Loading @@ -970,7 +985,7 @@ bool copy_system_profile(const std::string& system_profile, write(out_fd.get(), buffer, bytes); } if (flock(out_fd.get(), LOCK_UN) != 0) { PLOG(WARNING) << "Error unlocking profile " << data_profile_location; PLOG(WARNING) << "Error unlocking profile " << package_name; } // Use _exit since we don't want to run the global destructors in the child. // b/62597429 Loading Loading @@ -1269,8 +1284,8 @@ unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) { // Opens the reference profiles if needed. // Note that the reference profile might not exist so it's OK if the fd will be -1. Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname, const std::string& dex_path, bool profile_guided, bool is_public, int uid, bool is_secondary_dex) { const std::string& dex_path, const std::string& profile_name, bool profile_guided, bool is_public, int uid, bool is_secondary_dex) { // Public apps should not be compiled with profile information ever. Same goes for the special // package '*' used for the system server. if (!profile_guided || is_public || (pkgname[0] == '*')) { Loading @@ -1278,10 +1293,11 @@ Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname, } // Open reference profile in read only mode as dex2oat does not get write permissions. const std::string location = is_secondary_dex ? dex_path : pkgname; unique_fd ufd = open_reference_profile(uid, location, /*read_write*/false, is_secondary_dex); const auto& cleanup = [location, is_secondary_dex]() { clear_reference_profile(location.c_str(), is_secondary_dex); const std::string location = is_secondary_dex ? dex_path : profile_name; unique_fd ufd = open_reference_profile(uid, pkgname, location, /*read_write*/false, is_secondary_dex); const auto& cleanup = [pkgname, location, is_secondary_dex]() { clear_reference_profile(pkgname, location, is_secondary_dex); }; return Dex2oatFileWrapper(ufd.release(), cleanup); } Loading Loading @@ -1737,7 +1753,8 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char } // Analyze profiles. bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true); bool profile_was_updated = analyze_profiles(uid, pkgname, dex_path, /*is_secondary_dex*/true); // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return. exec_dexoptanalyzer(dex_path, Loading Loading @@ -1784,7 +1801,7 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char 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* class_loader_context, const char* se_info, bool downgrade, int target_sdk_version) { bool downgrade, int target_sdk_version, const char* profile_name) { CHECK(pkgname != nullptr); CHECK(pkgname[0] != 0); if ((dexopt_flags & ~DEXOPT_MASK) != 0) { Loading Loading @@ -1873,7 +1890,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins // Open the reference profile if needed. Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile( pkgname, dex_path, profile_guided, is_public, uid, is_secondary_dex); pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex); ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path); Loading Loading @@ -2032,9 +2049,9 @@ bool reconcile_secondary_dex_file(const std::string& dex_path, // Delete profiles. std::string current_profile = create_current_profile_path( multiuser_get_user_id(uid), dex_path, /*is_secondary*/true); multiuser_get_user_id(uid), pkgname, dex_path, /*is_secondary*/true); std::string reference_profile = create_reference_profile_path( dex_path, /*is_secondary*/true); pkgname, dex_path, /*is_secondary*/true); result = unlink_if_exists(current_profile) && result; result = unlink_if_exists(reference_profile) && result; Loading Loading @@ -2426,18 +2443,18 @@ bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src, } bool create_profile_snapshot(int32_t app_id, const std::string& package_name, const std::string& code_path) { const std::string& profile_name) { int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id); unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, code_path); unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name); if (snapshot_fd < 0) { return false; } std::vector<unique_fd> profiles_fd; unique_fd reference_profile_fd; open_profile_files(app_shared_gid, package_name, /*is_secondary_dex*/ false, &profiles_fd, &reference_profile_fd); open_profile_files(app_shared_gid, package_name, profile_name, /*is_secondary_dex*/ false, &profiles_fd, &reference_profile_fd); if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) { return false; } Loading @@ -2455,7 +2472,7 @@ bool create_profile_snapshot(int32_t app_id, const std::string& package_name, /* parent */ int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { LOG(WARNING) << "profman failed for " << package_name << ":" << code_path; LOG(WARNING) << "profman failed for " << package_name << ":" << profile_name; return false; } Loading cmds/installd/dexopt.h +18 −14 Original line number Diff line number Diff line Loading @@ -33,24 +33,25 @@ static constexpr int DEX2OAT_FOR_BOOT_IMAGE = 2; static constexpr int DEX2OAT_FOR_FILTER = 3; static constexpr int DEX2OAT_FOR_RELOCATION = 4; // Clear the reference profile for the primary apk of the given package. bool clear_primary_reference_profile(const std::string& pkgname); // Clear the current profile for the primary apk of the given package and user. bool clear_primary_current_profile(const std::string& pkgname, userid_t user); // Clear all current profile for the primary apk of the given package. bool clear_primary_current_profiles(const std::string& pkgname); bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path); // Clear the reference profile identified by the given profile name. bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name); // Clear the current profile identified by the given profile name (for single user). bool clear_primary_current_profile(const std::string& pkgname, const std::string& profile_name, userid_t user); // Clear all current profiles identified by the given profile name (all users). bool clear_primary_current_profiles(const std::string& pkgname, const std::string& profile_name); // Decide if profile guided compilation is needed or not based on existing profiles. // The analysis is done for the primary apks (base + splits) of the given package. // The analysis is done for a single profile name (which corresponds to a single code path). // Returns true if there is enough information in the current profiles that makes it // worth to recompile the package. // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). bool analyze_primary_profiles(uid_t uid, const std::string& pkgname); bool analyze_primary_profiles(uid_t uid, const std::string& pkgname, const std::string& profile_name); // Create a snapshot of the profile information for the given package and code path. // Create a snapshot of the profile information for the given package profile. // The profile snapshot is the aggregation of all existing profiles (all current user // profiles & the reference profile) and is meant to capture the all the profile information // without performing a merge into the reference profile which might impact future dex2oat Loading @@ -60,13 +61,14 @@ bool analyze_primary_profiles(uid_t uid, const std::string& pkgname); // The snapshot location is reference_profile_location.snapshot. If a snapshot is already // there, it will be truncated and overwritten. bool create_profile_snapshot(int32_t app_id, const std::string& package, const std::string& code_path); const std::string& profile_name); bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths); bool copy_system_profile(const std::string& system_profile, uid_t packageUid, const std::string& data_profile_location); const std::string& pkgname, const std::string& profile_name); bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path); Loading @@ -82,7 +84,7 @@ bool hash_secondary_dex_file(const std::string& dex_path, 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* class_loader_context, const char* se_info, bool downgrade, int target_sdk_version); bool downgrade, int target_sdk_version, const char* profile_name); bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, const char *instruction_set); Loading @@ -93,6 +95,8 @@ bool calculate_odex_file_path_default(char path[PKG_PATH_MAX], const char *apk_p bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src, const char *instruction_set); bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path); } // namespace installd } // namespace android Loading cmds/installd/otapreopt.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -1013,6 +1013,7 @@ private: } // Run dexopt with the parameters of package_parameters_. // TODO(calin): embed the profile name in the parameters. int Dexopt() { return dexopt(package_parameters_.apk_path, package_parameters_.uid, Loading @@ -1026,7 +1027,8 @@ private: package_parameters_.shared_libraries, package_parameters_.se_info, package_parameters_.downgrade, package_parameters_.target_sdk_version); package_parameters_.target_sdk_version, "primary.prof"); } int RunPreopt() { Loading cmds/installd/tests/installd_dexopt_test.cpp +65 −11 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
cmds/installd/InstalldNativeService.cpp +19 −12 Original line number Diff line number Diff line Loading @@ -107,6 +107,10 @@ namespace { constexpr const char* kDump = "android.permission.DUMP"; // TODO(calin): We can stop hardcoding this here once the PM passes the profile // name for all profile related operations. constexpr const char* kPrimaryProfileName = "primary.prof"; static binder::Status ok() { return binder::Status::ok(); } Loading Loading @@ -384,8 +388,9 @@ static bool prepare_app_profile_dir(const std::string& packageName, int32_t appI PLOG(ERROR) << "Failed to prepare " << profile_dir; return false; } const std::string profile_file = create_current_profile_path(userId, packageName, /*is_secondary_dex*/false); kPrimaryProfileName, /*is_secondary_dex*/false); // read-write only for the app user. if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << profile_file; Loading Loading @@ -546,10 +551,10 @@ binder::Status InstalldNativeService::clearAppProfiles(const std::string& packag std::lock_guard<std::recursive_mutex> lock(mLock); binder::Status res = ok(); if (!clear_primary_reference_profile(packageName)) { if (!clear_primary_reference_profile(packageName, kPrimaryProfileName)) { res = error("Failed to clear reference profile for " + packageName); } if (!clear_primary_current_profiles(packageName)) { if (!clear_primary_current_profiles(packageName, kPrimaryProfileName)) { res = error("Failed to clear current profiles for " + packageName); } return res; Loading Loading @@ -600,7 +605,7 @@ binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::st } } if (!only_cache) { if (!clear_primary_current_profile(packageName, userId)) { if (!clear_primary_current_profile(packageName, kPrimaryProfileName, userId)) { res = error("Failed to clear current profile for " + packageName); } } Loading Loading @@ -1869,7 +1874,8 @@ binder::Status InstalldNativeService::copySystemProfile(const std::string& syste ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName); *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName, kPrimaryProfileName); return ok(); } Loading @@ -1880,29 +1886,29 @@ binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::stri CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); *_aidl_return = analyze_primary_profiles(uid, packageName); *_aidl_return = analyze_primary_profiles(uid, packageName, kPrimaryProfileName); return ok(); } binder::Status InstalldNativeService::createProfileSnapshot(int32_t appId, const std::string& packageName, const std::string& codePath, bool* _aidl_return) { const std::string& packageName, const std::string& profileName, bool* _aidl_return) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); *_aidl_return = create_profile_snapshot(appId, packageName, codePath); *_aidl_return = create_profile_snapshot(appId, packageName, profileName); return ok(); } binder::Status InstalldNativeService::destroyProfileSnapshot(const std::string& packageName, const std::string& codePath) { const std::string& profileName) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PACKAGE_NAME(packageName); std::lock_guard<std::recursive_mutex> lock(mLock); std::string snapshot = create_snapshot_profile_path(packageName, codePath); std::string snapshot = create_snapshot_profile_path(packageName, profileName); if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) { return error("Failed to destroy profile snapshot for " + packageName + ":" + codePath); return error("Failed to destroy profile snapshot for " + packageName + ":" + profileName); } return ok(); } Loading @@ -1928,9 +1934,10 @@ binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t const char* volume_uuid = uuid ? uuid->c_str() : nullptr; const char* class_loader_context = classLoaderContext ? classLoaderContext->c_str() : nullptr; const char* se_info = seInfo ? seInfo->c_str() : nullptr; int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded, oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info, downgrade, targetSdkVersion); downgrade, targetSdkVersion, kPrimaryProfileName); return res ? error(res, "Failed to dexopt") : ok(); } Loading
cmds/installd/dexopt.cpp +73 −56 Original line number Diff line number Diff line Loading @@ -137,37 +137,43 @@ static bool clear_profile(const std::string& profile) { } // Clear the reference profile for the given location. // The location is the package name for primary apks or the dex path for secondary dex files. static bool clear_reference_profile(const std::string& location, bool is_secondary_dex) { return clear_profile(create_reference_profile_path(location, is_secondary_dex)); // The location is the profile name for primary apks or the dex path for secondary dex files. static bool clear_reference_profile(const std::string& package_name, const std::string& location, bool is_secondary_dex) { return clear_profile(create_reference_profile_path(package_name, location, is_secondary_dex)); } // Clear the reference profile for the given location. // The location is the package name for primary apks or the dex path for secondary dex files. static bool clear_current_profile(const std::string& pkgname, userid_t user, bool is_secondary_dex) { return clear_profile(create_current_profile_path(user, pkgname, is_secondary_dex)); // The location is the profile name for primary apks or the dex path for secondary dex files. static bool clear_current_profile(const std::string& package_name, const std::string& location, userid_t user, bool is_secondary_dex) { return clear_profile(create_current_profile_path(user, package_name, location, is_secondary_dex)); } // Clear the reference profile for the primary apk of the given package. bool clear_primary_reference_profile(const std::string& pkgname) { return clear_reference_profile(pkgname, /*is_secondary_dex*/false); // The location is the profile name for primary apks or the dex path for secondary dex files. bool clear_primary_reference_profile(const std::string& package_name, const std::string& location) { return clear_reference_profile(package_name, location, /*is_secondary_dex*/false); } // Clear all current profile for the primary apk of the given package. bool clear_primary_current_profiles(const std::string& pkgname) { // The location is the profile name for primary apks or the dex path for secondary dex files. bool clear_primary_current_profiles(const std::string& package_name, const std::string& location) { bool success = true; // For secondary dex files, we don't really need the user but we use it for sanity checks. std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); for (auto user : users) { success &= clear_current_profile(pkgname, user, /*is_secondary_dex*/false); success &= clear_current_profile(package_name, location, user, /*is_secondary_dex*/false); } return success; } // Clear the current profile for the primary apk of the given package and user. bool clear_primary_current_profile(const std::string& pkgname, userid_t user) { return clear_current_profile(pkgname, user, /*is_secondary_dex*/false); bool clear_primary_current_profile(const std::string& package_name, const std::string& location, userid_t user) { return clear_current_profile(package_name, location, user, /*is_secondary_dex*/false); } static int split_count(const char *str) Loading Loading @@ -638,29 +644,31 @@ static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t fla return fd; } static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location, bool is_secondary_dex) { std::string profile = create_current_profile_path(user, location, is_secondary_dex); static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& package_name, const std::string& location, bool is_secondary_dex) { std::string profile = create_current_profile_path(user, package_name, location, is_secondary_dex); return open_profile(uid, profile, O_RDONLY); } static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write, bool is_secondary_dex) { std::string profile = create_reference_profile_path(location, is_secondary_dex); static unique_fd open_reference_profile(uid_t uid, const std::string& package_name, const std::string& location, bool read_write, bool is_secondary_dex) { std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex); return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY); } static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name, const std::string& code_path) { std::string profile = create_snapshot_profile_path(package_name, code_path); const std::string& location) { std::string profile = create_snapshot_profile_path(package_name, location); return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC); } static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex, static void open_profile_files(uid_t uid, const std::string& package_name, const std::string& location, bool is_secondary_dex, /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) { // Open the reference profile in read-write mode as profman might need to save the merge. *reference_profile_fd = open_reference_profile(uid, location, /*read_write*/ true, is_secondary_dex); *reference_profile_fd = open_reference_profile(uid, package_name, location, /*read_write*/ true, is_secondary_dex); // For secondary dex files, we don't really need the user but we use it for sanity checks. // Note: the user owning the dex file should be the current user. Loading @@ -671,7 +679,8 @@ static void open_profile_files(uid_t uid, const std::string& location, bool is_s users = get_known_users(/*volume_uuid*/ nullptr); } for (auto user : users) { unique_fd profile_fd = open_current_profile(uid, user, location, is_secondary_dex); unique_fd profile_fd = open_current_profile(uid, user, package_name, location, is_secondary_dex); // Add to the lists only if both fds are valid. if (profile_fd.get() >= 0) { profiles_fd->push_back(std::move(profile_fd)); Loading Loading @@ -742,10 +751,12 @@ static void run_profman_merge(const std::vector<unique_fd>& profiles_fd, // worth to recompile the given location. // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). static bool analyze_profiles(uid_t uid, const std::string& location, bool is_secondary_dex) { static bool analyze_profiles(uid_t uid, const std::string& package_name, const std::string& location, bool is_secondary_dex) { std::vector<unique_fd> profiles_fd; unique_fd reference_profile_fd; open_profile_files(uid, location, is_secondary_dex, &profiles_fd, &reference_profile_fd); open_profile_files(uid, package_name, location, is_secondary_dex, &profiles_fd, &reference_profile_fd); if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) { // Skip profile guided compilation because no profiles were found. // Or if the reference profile info couldn't be opened. Loading Loading @@ -807,13 +818,14 @@ static bool analyze_profiles(uid_t uid, const std::string& location, bool is_sec if (should_clear_current_profiles) { if (is_secondary_dex) { // For secondary dex files, the owning user is the current user. clear_current_profile(location, multiuser_get_user_id(uid), is_secondary_dex); clear_current_profile(package_name, location, multiuser_get_user_id(uid), is_secondary_dex); } else { clear_primary_current_profiles(location); clear_primary_current_profiles(package_name, location); } } if (should_clear_reference_profile) { clear_reference_profile(location, is_secondary_dex); clear_reference_profile(package_name, location, is_secondary_dex); } return need_to_compile; } Loading @@ -824,8 +836,9 @@ static bool analyze_profiles(uid_t uid, const std::string& location, bool is_sec // worth to recompile the package. // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). bool analyze_primary_profiles(uid_t uid, const std::string& pkgname) { return analyze_profiles(uid, pkgname, /*is_secondary_dex*/false); bool analyze_primary_profiles(uid_t uid, const std::string& package_name, const std::string& profile_name) { return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false); } static void run_profman_dump(const std::vector<unique_fd>& profile_fds, Loading Loading @@ -868,7 +881,8 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat unique_fd reference_profile_fd; std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str()); open_profile_files(uid, pkgname, /*is_secondary_dex*/false, // TODO(calin): get the profile name as a parameter. open_profile_files(uid, pkgname, "primary.prof", /*is_secondary_dex*/false, &profile_fds, &reference_profile_fd); const bool has_reference_profile = (reference_profile_fd.get() != -1); Loading Loading @@ -918,10 +932,11 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat } bool copy_system_profile(const std::string& system_profile, uid_t packageUid, const std::string& data_profile_location) { uid_t packageUid, const std::string& package_name, const std::string& profile_name) { unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)); unique_fd out_fd(open_reference_profile(packageUid, data_profile_location, package_name, profile_name, /*read_write*/ true, /*secondary*/ false)); if (in_fd.get() < 0) { Loading @@ -929,7 +944,7 @@ bool copy_system_profile(const std::string& system_profile, return false; } if (out_fd.get() < 0) { PLOG(WARNING) << "Could not open profile " << data_profile_location; PLOG(WARNING) << "Could not open profile " << package_name; return false; } Loading @@ -942,7 +957,7 @@ bool copy_system_profile(const std::string& system_profile, if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) { if (errno != EWOULDBLOCK) { PLOG(WARNING) << "Error locking profile " << data_profile_location; PLOG(WARNING) << "Error locking profile " << package_name; } // This implies that the app owning this profile is running // (and has acquired the lock). Loading @@ -950,13 +965,13 @@ bool copy_system_profile(const std::string& system_profile, // The app never acquires the lock for the reference profiles of primary apks. // Only dex2oat from installd will do that. Since installd is single threaded // we should not see this case. Nevertheless be prepared for it. PLOG(WARNING) << "Failed to flock " << data_profile_location; PLOG(WARNING) << "Failed to flock " << package_name; return false; } bool truncated = ftruncate(out_fd.get(), 0) == 0; if (!truncated) { PLOG(WARNING) << "Could not truncate " << data_profile_location; PLOG(WARNING) << "Could not truncate " << package_name; } // Copy over data. Loading @@ -970,7 +985,7 @@ bool copy_system_profile(const std::string& system_profile, write(out_fd.get(), buffer, bytes); } if (flock(out_fd.get(), LOCK_UN) != 0) { PLOG(WARNING) << "Error unlocking profile " << data_profile_location; PLOG(WARNING) << "Error unlocking profile " << package_name; } // Use _exit since we don't want to run the global destructors in the child. // b/62597429 Loading Loading @@ -1269,8 +1284,8 @@ unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) { // Opens the reference profiles if needed. // Note that the reference profile might not exist so it's OK if the fd will be -1. Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname, const std::string& dex_path, bool profile_guided, bool is_public, int uid, bool is_secondary_dex) { const std::string& dex_path, const std::string& profile_name, bool profile_guided, bool is_public, int uid, bool is_secondary_dex) { // Public apps should not be compiled with profile information ever. Same goes for the special // package '*' used for the system server. if (!profile_guided || is_public || (pkgname[0] == '*')) { Loading @@ -1278,10 +1293,11 @@ Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname, } // Open reference profile in read only mode as dex2oat does not get write permissions. const std::string location = is_secondary_dex ? dex_path : pkgname; unique_fd ufd = open_reference_profile(uid, location, /*read_write*/false, is_secondary_dex); const auto& cleanup = [location, is_secondary_dex]() { clear_reference_profile(location.c_str(), is_secondary_dex); const std::string location = is_secondary_dex ? dex_path : profile_name; unique_fd ufd = open_reference_profile(uid, pkgname, location, /*read_write*/false, is_secondary_dex); const auto& cleanup = [pkgname, location, is_secondary_dex]() { clear_reference_profile(pkgname, location, is_secondary_dex); }; return Dex2oatFileWrapper(ufd.release(), cleanup); } Loading Loading @@ -1737,7 +1753,8 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char } // Analyze profiles. bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true); bool profile_was_updated = analyze_profiles(uid, pkgname, dex_path, /*is_secondary_dex*/true); // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return. exec_dexoptanalyzer(dex_path, Loading Loading @@ -1784,7 +1801,7 @@ static bool process_secondary_dex_dexopt(const std::string& dex_path, const char 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* class_loader_context, const char* se_info, bool downgrade, int target_sdk_version) { bool downgrade, int target_sdk_version, const char* profile_name) { CHECK(pkgname != nullptr); CHECK(pkgname[0] != 0); if ((dexopt_flags & ~DEXOPT_MASK) != 0) { Loading Loading @@ -1873,7 +1890,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins // Open the reference profile if needed. Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile( pkgname, dex_path, profile_guided, is_public, uid, is_secondary_dex); pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex); ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path); Loading Loading @@ -2032,9 +2049,9 @@ bool reconcile_secondary_dex_file(const std::string& dex_path, // Delete profiles. std::string current_profile = create_current_profile_path( multiuser_get_user_id(uid), dex_path, /*is_secondary*/true); multiuser_get_user_id(uid), pkgname, dex_path, /*is_secondary*/true); std::string reference_profile = create_reference_profile_path( dex_path, /*is_secondary*/true); pkgname, dex_path, /*is_secondary*/true); result = unlink_if_exists(current_profile) && result; result = unlink_if_exists(reference_profile) && result; Loading Loading @@ -2426,18 +2443,18 @@ bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src, } bool create_profile_snapshot(int32_t app_id, const std::string& package_name, const std::string& code_path) { const std::string& profile_name) { int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id); unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, code_path); unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name); if (snapshot_fd < 0) { return false; } std::vector<unique_fd> profiles_fd; unique_fd reference_profile_fd; open_profile_files(app_shared_gid, package_name, /*is_secondary_dex*/ false, &profiles_fd, &reference_profile_fd); open_profile_files(app_shared_gid, package_name, profile_name, /*is_secondary_dex*/ false, &profiles_fd, &reference_profile_fd); if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) { return false; } Loading @@ -2455,7 +2472,7 @@ bool create_profile_snapshot(int32_t app_id, const std::string& package_name, /* parent */ int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { LOG(WARNING) << "profman failed for " << package_name << ":" << code_path; LOG(WARNING) << "profman failed for " << package_name << ":" << profile_name; return false; } Loading
cmds/installd/dexopt.h +18 −14 Original line number Diff line number Diff line Loading @@ -33,24 +33,25 @@ static constexpr int DEX2OAT_FOR_BOOT_IMAGE = 2; static constexpr int DEX2OAT_FOR_FILTER = 3; static constexpr int DEX2OAT_FOR_RELOCATION = 4; // Clear the reference profile for the primary apk of the given package. bool clear_primary_reference_profile(const std::string& pkgname); // Clear the current profile for the primary apk of the given package and user. bool clear_primary_current_profile(const std::string& pkgname, userid_t user); // Clear all current profile for the primary apk of the given package. bool clear_primary_current_profiles(const std::string& pkgname); bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path); // Clear the reference profile identified by the given profile name. bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name); // Clear the current profile identified by the given profile name (for single user). bool clear_primary_current_profile(const std::string& pkgname, const std::string& profile_name, userid_t user); // Clear all current profiles identified by the given profile name (all users). bool clear_primary_current_profiles(const std::string& pkgname, const std::string& profile_name); // Decide if profile guided compilation is needed or not based on existing profiles. // The analysis is done for the primary apks (base + splits) of the given package. // The analysis is done for a single profile name (which corresponds to a single code path). // Returns true if there is enough information in the current profiles that makes it // worth to recompile the package. // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). bool analyze_primary_profiles(uid_t uid, const std::string& pkgname); bool analyze_primary_profiles(uid_t uid, const std::string& pkgname, const std::string& profile_name); // Create a snapshot of the profile information for the given package and code path. // Create a snapshot of the profile information for the given package profile. // The profile snapshot is the aggregation of all existing profiles (all current user // profiles & the reference profile) and is meant to capture the all the profile information // without performing a merge into the reference profile which might impact future dex2oat Loading @@ -60,13 +61,14 @@ bool analyze_primary_profiles(uid_t uid, const std::string& pkgname); // The snapshot location is reference_profile_location.snapshot. If a snapshot is already // there, it will be truncated and overwritten. bool create_profile_snapshot(int32_t app_id, const std::string& package, const std::string& code_path); const std::string& profile_name); bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths); bool copy_system_profile(const std::string& system_profile, uid_t packageUid, const std::string& data_profile_location); const std::string& pkgname, const std::string& profile_name); bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path); Loading @@ -82,7 +84,7 @@ bool hash_secondary_dex_file(const std::string& dex_path, 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* class_loader_context, const char* se_info, bool downgrade, int target_sdk_version); bool downgrade, int target_sdk_version, const char* profile_name); bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, const char *instruction_set); Loading @@ -93,6 +95,8 @@ bool calculate_odex_file_path_default(char path[PKG_PATH_MAX], const char *apk_p bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src, const char *instruction_set); bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path); } // namespace installd } // namespace android Loading
cmds/installd/otapreopt.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -1013,6 +1013,7 @@ private: } // Run dexopt with the parameters of package_parameters_. // TODO(calin): embed the profile name in the parameters. int Dexopt() { return dexopt(package_parameters_.apk_path, package_parameters_.uid, Loading @@ -1026,7 +1027,8 @@ private: package_parameters_.shared_libraries, package_parameters_.se_info, package_parameters_.downgrade, package_parameters_.target_sdk_version); package_parameters_.target_sdk_version, "primary.prof"); } int RunPreopt() { Loading
cmds/installd/tests/installd_dexopt_test.cpp +65 −11 File changed.Preview size limit exceeded, changes collapsed. Show changes