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

Commit f966f2a5 authored by Mathieu Chartier's avatar Mathieu Chartier
Browse files

Add copy system profile functionality

Test: Flash preopted speed-profile maps.
Test: Confirm ref profile exists.
Test: Close maps, recompile with speed-profile, test the profile was used.
Test: Launch maps, do some stuff until cur profile exists.
Test: Re-compile with speed-profile and confirm cur merged over ref correctly.

Bug: 38032017

Change-Id: I19c8009ad61213bdcb52f010329eb459ca82f92b
parent bd32a5d7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1779,6 +1779,16 @@ binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::strin
    return ok();
}

// Copy the contents of a system profile over the data profile.
binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
        int32_t packageUid, const std::string& packageName, bool* _aidl_return) {
    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);
    return ok();
}

// TODO: Consider returning error codes.
binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
        bool* _aidl_return) {
+2 −0
Original line number Diff line number Diff line
@@ -91,6 +91,8 @@ public:
    binder::Status mergeProfiles(int32_t uid, const std::string& packageName, bool* _aidl_return);
    binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
            const std::string& codePaths, bool* _aidl_return);
    binder::Status copySystemProfile(const std::string& systemProfile,
            int32_t uid, const std::string& packageName, bool* _aidl_return);
    binder::Status clearAppProfiles(const std::string& packageName);
    binder::Status destroyAppProfiles(const std::string& packageName);

+2 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ interface IInstalld {

    boolean mergeProfiles(int uid, @utf8InCpp String packageName);
    boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
    boolean copySystemProfile(@utf8InCpp String systemProfile, int uid,
            @utf8InCpp String packageName);
    void clearAppProfiles(@utf8InCpp String packageName);
    void destroyAppProfiles(@utf8InCpp String packageName);

+60 −0
Original line number Diff line number Diff line
@@ -847,6 +847,66 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat
    return true;
}

bool copy_system_profile(const std::string& system_profile,
        uid_t packageUid, const std::string& data_profile_location) {
    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,
                     /*read_write*/ true,
                     /*secondary*/ false));
    if (in_fd.get() < 0) {
        PLOG(WARNING) << "Could not open profile " << system_profile;
        return false;
    }
    if (out_fd.get() < 0) {
        PLOG(WARNING) << "Could not open profile " << data_profile_location;
        return false;
    }

    pid_t pid = fork();
    if (pid == 0) {
        /* child -- drop privileges before continuing */
        drop_capabilities(packageUid);

        if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
            if (errno != EWOULDBLOCK) {
                PLOG(WARNING) << "Error locking profile " << data_profile_location;
            }
            // This implies that the app owning this profile is running
            // (and has acquired the lock).
            //
            // 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;
            return false;
        }

        bool truncated = ftruncate(out_fd.get(), 0) == 0;
        if (!truncated) {
            PLOG(WARNING) << "Could not truncate " << data_profile_location;
        }

        // Copy over data.
        static constexpr size_t kBufferSize = 4 * 1024;
        char buffer[kBufferSize];
        while (true) {
            ssize_t bytes = read(in_fd.get(), buffer, kBufferSize);
            if (bytes == 0) {
                break;
            }
            write(out_fd.get(), buffer, bytes);
        }
        if (flock(out_fd.get(), LOCK_UN) != 0) {
            PLOG(WARNING) << "Error unlocking profile " << data_profile_location;
        }
        exit(0);
    }
    /* parent */
    int return_code = wait_child(pid);
    return return_code == 0;
}

static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
  // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
  if (EndsWith(oat_path, ".dex")) {
+4 −0
Original line number Diff line number Diff line
@@ -50,6 +50,10 @@ bool analyze_primary_profiles(uid_t uid, const std::string& pkgname);

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);

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,