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

Commit 39557149 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi Committed by Android (Google) Code Review
Browse files

Merge "[incremental] Use file range mapping for .so if available" into sc-dev

parents b86a4ca6 a5946f70
Loading
Loading
Loading
Loading
+40 −4
Original line number Diff line number Diff line
@@ -1617,7 +1617,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
    // Need a shared pointer: will be passing it into all unpacking jobs.
    std::shared_ptr<ZipArchive> zipFile(zipFileHandle, [](ZipArchiveHandle h) { CloseArchive(h); });
    void* cookie = nullptr;
    const auto libFilePrefix = path::join(constants().libDir, abi) + "/";
    const auto libFilePrefix = path::join(constants().libDir, abi) += "/";
    if (StartIteration(zipFile.get(), &cookie, libFilePrefix, constants().libSuffix)) {
        LOG(ERROR) << "Failed to start zip iteration for " << apkFullPath;
        return false;
@@ -1627,6 +1627,17 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_

    auto openZipTs = Clock::now();

    auto mapFiles = (mIncFs->features() & incfs::Features::v2);
    incfs::FileId sourceId;
    if (mapFiles) {
        sourceId = mIncFs->getFileId(ifs->control, apkFullPath);
        if (!incfs::isValidFileId(sourceId)) {
            LOG(WARNING) << "Error getting IncFS file ID for apk path '" << apkFullPath
                         << "', mapping disabled";
            mapFiles = false;
        }
    }

    std::vector<Job> jobQueue;
    ZipEntry entry;
    std::string_view fileName;
@@ -1635,13 +1646,16 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
            continue;
        }

        const auto entryUncompressed = entry.method == kCompressStored;
        const auto entryPageAligned = (entry.offset & (constants().blockSize - 1)) == 0;

        if (!extractNativeLibs) {
            // ensure the file is properly aligned and unpacked
            if (entry.method != kCompressStored) {
            if (!entryUncompressed) {
                LOG(WARNING) << "Library " << fileName << " must be uncompressed to mmap it";
                return false;
            }
            if ((entry.offset & (constants().blockSize - 1)) != 0) {
            if (!entryPageAligned) {
                LOG(WARNING) << "Library " << fileName
                             << " must be page-aligned to mmap it, offset = 0x" << std::hex
                             << entry.offset;
@@ -1665,6 +1679,28 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
            continue;
        }

        if (mapFiles && entryUncompressed && entryPageAligned && entry.uncompressed_length > 0) {
            incfs::NewMappedFileParams mappedFileParams = {
                    .sourceId = sourceId,
                    .sourceOffset = entry.offset,
                    .size = entry.uncompressed_length,
            };

            if (auto res = mIncFs->makeMappedFile(ifs->control, targetLibPathAbsolute, 0755,
                                                  mappedFileParams);
                res == 0) {
                if (perfLoggingEnabled()) {
                    auto doneTs = Clock::now();
                    LOG(INFO) << "incfs: Mapped " << libName << ": "
                              << elapsedMcs(startFileTs, doneTs) << "mcs";
                }
                continue;
            } else {
                LOG(WARNING) << "Failed to map file for: '" << targetLibPath << "' errno: " << res
                             << "; falling back to full extraction";
            }
        }

        // Create new lib file without signature info
        incfs::NewFileParams libFileParams = {
                .size = entry.uncompressed_length,
@@ -1673,7 +1709,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
                .metadata = {targetLibPath.c_str(), (IncFsSize)targetLibPath.size()},
        };
        incfs::FileId libFileId = idFromMetadata(targetLibPath);
        if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0777, libFileId,
        if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0755, libFileId,
                                        libFileParams)) {
            LOG(ERROR) << "Failed to make file for: " << targetLibPath << " errno: " << res;
            // If one lib file fails to be created, abort others as well
+6 −1
Original line number Diff line number Diff line
@@ -134,10 +134,11 @@ private:
    } mLooper;
};

class RealIncFs : public IncFsWrapper {
class RealIncFs final : public IncFsWrapper {
public:
    RealIncFs() = default;
    ~RealIncFs() final = default;
    Features features() const final { return incfs::features(); }
    void listExistingMounts(const ExistingMountCallback& cb) const final {
        for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
            auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
@@ -153,6 +154,10 @@ public:
                       incfs::NewFileParams params) const final {
        return incfs::makeFile(control, path, mode, id, params);
    }
    ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
                             incfs::NewMappedFileParams params) const final {
        return incfs::makeMappedFile(control, path, mode, params);
    }
    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
        return incfs::makeDir(control, path, mode);
    }
+4 −0
Original line number Diff line number Diff line
@@ -77,18 +77,22 @@ public:
    using ErrorCode = incfs::ErrorCode;
    using UniqueFd = incfs::UniqueFd;
    using WaitResult = incfs::WaitResult;
    using Features = incfs::Features;

    using ExistingMountCallback =
            std::function<void(std::string_view root, std::string_view backingDir,
                               std::span<std::pair<std::string_view, std::string_view>> binds)>;

    virtual ~IncFsWrapper() = default;
    virtual Features features() const = 0;
    virtual void listExistingMounts(const ExistingMountCallback& cb) const = 0;
    virtual Control openMount(std::string_view path) const = 0;
    virtual Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
                                  IncFsFd blocksWritten) const = 0;
    virtual ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
                               incfs::NewFileParams params) const = 0;
    virtual ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
                                     incfs::NewMappedFileParams params) const = 0;
    virtual ErrorCode makeDir(const Control& control, std::string_view path, int mode) const = 0;
    virtual ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const = 0;
    virtual incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const = 0;
+4 −0
Original line number Diff line number Diff line
@@ -322,6 +322,7 @@ private:

class MockIncFs : public IncFsWrapper {
public:
    MOCK_CONST_METHOD0(features, Features());
    MOCK_CONST_METHOD1(listExistingMounts, void(const ExistingMountCallback& cb));
    MOCK_CONST_METHOD1(openMount, Control(std::string_view path));
    MOCK_CONST_METHOD4(createControl,
@@ -330,6 +331,9 @@ public:
    MOCK_CONST_METHOD5(makeFile,
                       ErrorCode(const Control& control, std::string_view path, int mode, FileId id,
                                 NewFileParams params));
    MOCK_CONST_METHOD4(makeMappedFile,
                       ErrorCode(const Control& control, std::string_view path, int mode,
                                 NewMappedFileParams params));
    MOCK_CONST_METHOD3(makeDir, ErrorCode(const Control& control, std::string_view path, int mode));
    MOCK_CONST_METHOD3(makeDirs,
                       ErrorCode(const Control& control, std::string_view path, int mode));