Loading cmds/installd/dexopt.cpp +25 −2 Original line number Diff line number Diff line Loading @@ -2818,14 +2818,22 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, // We do this to avoid opening a huge a amount of files. static constexpr size_t kAggregationBatchSize = 10; std::vector<unique_fd> profiles_fd; for (size_t i = 0; i < profiles.size(); ) { std::vector<unique_fd> profiles_fd; for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) { unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY); if (fd.get() >= 0) { profiles_fd.push_back(std::move(fd)); } } // We aggregate (read & write) into the same fd multiple times in a row. // We need to reset the cursor every time to ensure we read the whole file every time. if (TEMP_FAILURE_RETRY(lseek(snapshot_fd, 0, SEEK_SET)) == static_cast<off_t>(-1)) { PLOG(ERROR) << "Cannot reset position for snapshot profile"; return false; } RunProfman args; args.SetupMerge(profiles_fd, snapshot_fd, Loading @@ -2843,12 +2851,27 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, /* parent */ int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name; return false; } return true; // Verify that profman finished successfully. int profman_code = WEXITSTATUS(return_code); switch (profman_code) { case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES: // fall through case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall through case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING: LOG(WARNING) << "profman error for " << package_name << ":" << profile_name << ":" << profman_code; return false; default: // Other return codes are ok. continue; } } return true; } Loading cmds/installd/tests/installd_dexopt_test.cpp +45 −1 Original line number Diff line number Diff line Loading @@ -1130,16 +1130,60 @@ TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) { class BootProfileTest : public ProfileTest { public: virtual void setup() { std::vector<const std::string> extra_apps_; std::vector<int64_t> extra_ce_data_inodes_; virtual void SetUp() { ProfileTest::SetUp(); intial_android_profiles_dir = android_profiles_dir; // Generate profiles for some extra apps. // When merging boot profile we split profiles into small groups to avoid // opening a lot of file descriptors at the same time. // (Currently the group size for aggregation is 10) // // To stress test that works fine, create profile for more apps. createAppProfilesForBootMerge(21); } virtual void TearDown() { android_profiles_dir = intial_android_profiles_dir; deleteAppProfilesForBootMerge(); ProfileTest::TearDown(); } void createAppProfilesForBootMerge(size_t number_of_profiles) { for (size_t i = 0; i < number_of_profiles; i++) { int64_t ce_data_inode; std::string package_name = "dummy_test_pkg" + std::to_string(i); LOG(INFO) << package_name; ASSERT_BINDER_SUCCESS(service_->createAppData( volume_uuid_, package_name, kTestUserId, kAppDataFlags, kTestAppUid, se_info_, kOSdkVersion, &ce_data_inode)); extra_apps_.push_back(package_name); extra_ce_data_inodes_.push_back(ce_data_inode); std::string profile = create_current_profile_path( kTestUserId, package_name, kPrimaryProfile, /*is_secondary_dex*/ false); SetupProfile(profile, kTestAppUid, kTestAppGid, 0600, 1); } } void deleteAppProfilesForBootMerge() { if (kDebug) { return; } for (size_t i = 0; i < extra_apps_.size(); i++) { service_->destroyAppData( volume_uuid_, extra_apps_[i], kTestUserId, kAppDataFlags, extra_ce_data_inodes_[i]); } } void UpdateAndroidProfilesDir(const std::string& profile_dir) { android_profiles_dir = profile_dir; // We need to create the reference profile directory in the new profile dir. Loading Loading
cmds/installd/dexopt.cpp +25 −2 Original line number Diff line number Diff line Loading @@ -2818,14 +2818,22 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, // We do this to avoid opening a huge a amount of files. static constexpr size_t kAggregationBatchSize = 10; std::vector<unique_fd> profiles_fd; for (size_t i = 0; i < profiles.size(); ) { std::vector<unique_fd> profiles_fd; for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) { unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY); if (fd.get() >= 0) { profiles_fd.push_back(std::move(fd)); } } // We aggregate (read & write) into the same fd multiple times in a row. // We need to reset the cursor every time to ensure we read the whole file every time. if (TEMP_FAILURE_RETRY(lseek(snapshot_fd, 0, SEEK_SET)) == static_cast<off_t>(-1)) { PLOG(ERROR) << "Cannot reset position for snapshot profile"; return false; } RunProfman args; args.SetupMerge(profiles_fd, snapshot_fd, Loading @@ -2843,12 +2851,27 @@ static bool create_boot_image_profile_snapshot(const std::string& package_name, /* parent */ int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name; return false; } return true; // Verify that profman finished successfully. int profman_code = WEXITSTATUS(return_code); switch (profman_code) { case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES: // fall through case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall through case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING: LOG(WARNING) << "profman error for " << package_name << ":" << profile_name << ":" << profman_code; return false; default: // Other return codes are ok. continue; } } return true; } Loading
cmds/installd/tests/installd_dexopt_test.cpp +45 −1 Original line number Diff line number Diff line Loading @@ -1130,16 +1130,60 @@ TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) { class BootProfileTest : public ProfileTest { public: virtual void setup() { std::vector<const std::string> extra_apps_; std::vector<int64_t> extra_ce_data_inodes_; virtual void SetUp() { ProfileTest::SetUp(); intial_android_profiles_dir = android_profiles_dir; // Generate profiles for some extra apps. // When merging boot profile we split profiles into small groups to avoid // opening a lot of file descriptors at the same time. // (Currently the group size for aggregation is 10) // // To stress test that works fine, create profile for more apps. createAppProfilesForBootMerge(21); } virtual void TearDown() { android_profiles_dir = intial_android_profiles_dir; deleteAppProfilesForBootMerge(); ProfileTest::TearDown(); } void createAppProfilesForBootMerge(size_t number_of_profiles) { for (size_t i = 0; i < number_of_profiles; i++) { int64_t ce_data_inode; std::string package_name = "dummy_test_pkg" + std::to_string(i); LOG(INFO) << package_name; ASSERT_BINDER_SUCCESS(service_->createAppData( volume_uuid_, package_name, kTestUserId, kAppDataFlags, kTestAppUid, se_info_, kOSdkVersion, &ce_data_inode)); extra_apps_.push_back(package_name); extra_ce_data_inodes_.push_back(ce_data_inode); std::string profile = create_current_profile_path( kTestUserId, package_name, kPrimaryProfile, /*is_secondary_dex*/ false); SetupProfile(profile, kTestAppUid, kTestAppGid, 0600, 1); } } void deleteAppProfilesForBootMerge() { if (kDebug) { return; } for (size_t i = 0; i < extra_apps_.size(); i++) { service_->destroyAppData( volume_uuid_, extra_apps_[i], kTestUserId, kAppDataFlags, extra_ce_data_inodes_[i]); } } void UpdateAndroidProfilesDir(const std::string& profile_dir) { android_profiles_dir = profile_dir; // We need to create the reference profile directory in the new profile dir. Loading