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

Commit c3b049e0 authored by Calin Juravle's avatar Calin Juravle Committed by Andreas Gampe
Browse files

[installd] Prepare profiles for app code paths

Implement profile preparation for individual application code paths.

The preparation is:
- create the current profile
- merge the profile from the dex metadata file (if present) into the
reference profile.

Note: currently the current profile is created as part of
InstalldNativeService::createAppData for the entire package. That logic
does not support dex metadata or individual code paths and will be removed
once the PackageManager switches over the new method.

(cherry picked from commit bc5ab878)

Test: installd_dexopt_test
Bug: 30934496
Merged-In: I2aeddcda7b78017bd46838985bef5f92a79d4573
Change-Id: I2aeddcda7b78017bd46838985bef5f92a79d4573
parent 824a64db
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2480,5 +2480,17 @@ binder::Status InstalldNativeService::isQuotaSupported(
    return ok();
}

binder::Status InstalldNativeService::prepareAppProfile(const std::string& packageName,
        int32_t userId, int32_t appId, const std::string& profileName, const std::string& codePath,
        const std::unique_ptr<std::string>& dexMetadata, bool* _aidl_return) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    *_aidl_return = prepare_app_profile(packageName, userId, appId, profileName, codePath,
        dexMetadata);
    return ok();
}

}  // namespace installd
}  // namespace android
+5 −0
Original line number Diff line number Diff line
@@ -131,6 +131,11 @@ public:
    binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
            bool* _aidl_return);

    binder::Status prepareAppProfile(const std::string& packageName,
            int32_t userId, int32_t appId, const std::string& profileName,
            const std::string& codePath, const std::unique_ptr<std::string>& dexMetadata,
            bool* _aidl_return);

private:
    std::recursive_mutex mLock;

+4 −0
Original line number Diff line number Diff line
@@ -92,4 +92,8 @@ interface IInstalld {

    void invalidateMounts();
    boolean isQuotaSupported(@nullable @utf8InCpp String uuid);

    boolean prepareAppProfile(@utf8InCpp String packageName,
        int userId, int appId, @utf8InCpp String profileName, @utf8InCpp String codePath,
        @nullable @utf8InCpp String dexMetadata);
}
+50 −0
Original line number Diff line number Diff line
@@ -2479,5 +2479,55 @@ bool create_profile_snapshot(int32_t app_id, const std::string& package_name,
    return true;
}

bool prepare_app_profile(const std::string& package_name,
                         userid_t user_id,
                         appid_t app_id,
                         const std::string& profile_name,
                         const std::string& code_path ATTRIBUTE_UNUSED,
                         const std::unique_ptr<std::string>& dex_metadata) {
    // Prepare the current profile.
    std::string cur_profile  = create_current_profile_path(user_id, package_name, profile_name,
            /*is_secondary_dex*/ false);
    uid_t uid = multiuser_get_uid(user_id, app_id);
    if (fs_prepare_file_strict(cur_profile.c_str(), 0600, uid, uid) != 0) {
        PLOG(ERROR) << "Failed to prepare " << cur_profile;
        return false;
    }

    // Check if we need to install the profile from the dex metadata.
    if (dex_metadata == nullptr) {
        return true;
    }

    // We have a dex metdata. Merge the profile into the reference profile.
    unique_fd ref_profile_fd = open_reference_profile(uid, package_name, profile_name,
            /*read_write*/ true, /*is_secondary_dex*/ false);
    unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
            open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
    std::vector<unique_fd> profiles_fd;
    profiles_fd.push_back(std::move(dex_metadata_fd));

    pid_t pid = fork();
    if (pid == 0) {
        /* child -- drop privileges before continuing */
        gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
        drop_capabilities(app_shared_gid);

        // TODO(calin): the dex metadata profile might embed different names for the
        // same code path (e.g. YouTube.apk or base.apk, depending on how the initial
        // profile was captured). We should pass the code path to adjust the names in the profile.
        run_profman_merge(profiles_fd, ref_profile_fd);
        exit(42);   /* only get here on exec failure */
    }

    /* parent */
    int return_code = wait_child(pid);
    if (!WIFEXITED(return_code)) {
        PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
        return false;
    }
    return true;
}

}  // namespace installd
}  // namespace android
+11 −0
Original line number Diff line number Diff line
@@ -70,6 +70,17 @@ bool copy_system_profile(const std::string& system_profile,
                         const std::string& pkgname,
                         const std::string& profile_name);

// Prepare the app profile for the given code path:
//  - create the current profile using profile_name
//  - merge the profile from the dex metadata file (if present) into
//    the reference profile.
bool prepare_app_profile(const std::string& package_name,
                         userid_t user_id,
                         appid_t app_id,
                         const std::string& profile_name,
                         const std::string& code_path,
                         const std::unique_ptr<std::string>& dex_metadata);

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,
Loading