diff options
| -rw-r--r-- | cmds/installd/dexopt.cpp | 27 | ||||
| -rw-r--r-- | cmds/installd/tests/installd_dexopt_test.cpp | 46 |
2 files changed, 70 insertions, 3 deletions
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index 838d11d6d8..6205affd98 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -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, @@ -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; } diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp index 0212bc5564..226d72f995 100644 --- a/cmds/installd/tests/installd_dexopt_test.cpp +++ b/cmds/installd/tests/installd_dexopt_test.cpp @@ -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. |