Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a64fb518 authored by Calin Juravle's avatar Calin Juravle
Browse files

Fix BootImageProfile aggregation

An early return statement would make the aggregation stop sooner than it
should have.

Bug: 139884006
Test: installd tests
Change-Id: Ia5adb01090901286c5b60df5b717ed6229566c25
parent 7618ed32
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -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;
}

+45 −1
Original line number Diff line number Diff line
@@ -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.