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

Commit 3fde572a authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi
Browse files

Fix the progress getting for mapped files

Mapped files don't support querying their loading progress,
so we should simply skip them - they are already a part of
some other file, and will get accounted for loading when
that file's progress get queried

+ a bunch of small improvements

Bug: 180535478
Test: atest service.incremental_test, adb install --incremental
  with mapped native libs

Change-Id: Ifc8a402144f2f3669a0419124fb0f35d7002190a
(cherry picked from commit 7731ebd1)
parent a5946f70
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -1936,25 +1936,33 @@ IncrementalService::LoadingProgress IncrementalService::getLoadingProgress(
}

IncrementalService::LoadingProgress IncrementalService::getLoadingProgressFromPath(
        const IncFsMount& ifs, std::string_view storagePath, bool stopOnFirstIncomplete) const {
    ssize_t totalBlocks = 0, filledBlocks = 0;
    const auto filePaths = mFs->listFilesRecursive(storagePath);
    for (const auto& filePath : filePaths) {
        const IncFsMount& ifs, std::string_view storagePath,
        const bool stopOnFirstIncomplete) const {
    ssize_t totalBlocks = 0, filledBlocks = 0, error = 0;
    mFs->listFilesRecursive(storagePath, [&, this](auto filePath) {
        const auto [filledBlocksCount, totalBlocksCount] =
                mIncFs->countFilledBlocks(ifs.control, filePath);
        if (filledBlocksCount == -EOPNOTSUPP || filledBlocksCount == -ENOTSUP ||
            filledBlocksCount == -ENOENT) {
            // a kind of a file that's not really being loaded, e.g. a mapped range
            // an older IncFS used to return ENOENT in this case, so handle it the same way
            return true;
        }
        if (filledBlocksCount < 0) {
            LOG(ERROR) << "getLoadingProgress failed to get filled blocks count for: " << filePath
                       << " errno: " << filledBlocksCount;
            return {filledBlocksCount, filledBlocksCount};
            error = filledBlocksCount;
            return false;
        }
        totalBlocks += totalBlocksCount;
        filledBlocks += filledBlocksCount;
        if (stopOnFirstIncomplete && filledBlocks < totalBlocks) {
            break;
        }
            return false;
        }
        return true;
    });

    return {filledBlocks, totalBlocks};
    return error ? LoadingProgress{error, error} : LoadingProgress{filledBlocks, totalBlocks};
}

bool IncrementalService::updateLoadingProgress(
+7 −8
Original line number Diff line number Diff line
@@ -287,11 +287,10 @@ private:
            auto it = mJobs.begin();
            // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
            for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
                auto job = std::move(it->what);
                mJobs.erase(it);
                auto jobNode = mJobs.extract(it);

                lock.unlock();
                job();
                jobNode.value().what();
                lock.lock();
            }
            nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
@@ -313,20 +312,20 @@ private:
    std::thread mThread;
};

class RealFsWrapper : public FsWrapper {
class RealFsWrapper final : public FsWrapper {
public:
    RealFsWrapper() = default;
    ~RealFsWrapper() = default;

    std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const final {
        std::vector<std::string> files;
    void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const final {
        for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
            if (!entry.is_regular_file()) {
                continue;
            }
            files.push_back(entry.path().c_str());
            if (!onFile(entry.path().native())) {
                break;
            }
        }
        return files;
    }
};

+7 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <android-base/function_ref.h>
#include <android-base/unique_fd.h>
#include <android/content/pm/DataLoaderParamsParcel.h>
#include <android/content/pm/FileSystemControlParcel.h>
@@ -79,8 +80,8 @@ public:
    using WaitResult = incfs::WaitResult;
    using Features = incfs::Features;

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

    virtual ~IncFsWrapper() = default;
@@ -152,7 +153,9 @@ public:
class FsWrapper {
public:
    virtual ~FsWrapper() = default;
    virtual std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const = 0;

    using FileCallback = android::base::function_ref<bool(std::string_view)>;
    virtual void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const = 0;
};

class ServiceManagerWrapper {
+7 −7
Original line number Diff line number Diff line
@@ -543,16 +543,16 @@ public:

class MockFsWrapper : public FsWrapper {
public:
    MOCK_CONST_METHOD1(listFilesRecursive, std::vector<std::string>(std::string_view));
    void hasNoFile() {
        ON_CALL(*this, listFilesRecursive(_)).WillByDefault(Return(std::vector<std::string>()));
    }
    MOCK_CONST_METHOD2(listFilesRecursive, void(std::string_view, FileCallback));
    void hasNoFile() { ON_CALL(*this, listFilesRecursive(_, _)).WillByDefault(Return()); }
    void hasFiles() {
        ON_CALL(*this, listFilesRecursive(_))
        ON_CALL(*this, listFilesRecursive(_, _))
                .WillByDefault(Invoke(this, &MockFsWrapper::fakeFiles));
    }
    std::vector<std::string> fakeFiles(std::string_view directoryPath) {
        return {"base.apk", "split.apk", "lib/a.so"};
    void fakeFiles(std::string_view directoryPath, FileCallback onFile) {
        for (auto file : {"base.apk", "split.apk", "lib/a.so"}) {
            if (!onFile(file)) break;
        }
    }
};