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

Commit 4a217921 authored by Cody Northrop's avatar Cody Northrop Committed by Android (Google) Code Review
Browse files

Merge "Reland "EGL: Refactor multifile blobcache""

parents ff74a409 6cca6c23
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -144,6 +144,7 @@ cc_library_static {
    srcs: [
    srcs: [
        "EGL/BlobCache.cpp",
        "EGL/BlobCache.cpp",
        "EGL/FileBlobCache.cpp",
        "EGL/FileBlobCache.cpp",
        "EGL/MultifileBlobCache.cpp",
    ],
    ],
    export_include_dirs: ["EGL"],
    export_include_dirs: ["EGL"],
}
}
@@ -160,7 +161,6 @@ cc_library_shared {
    srcs: [
    srcs: [
        "EGL/egl_tls.cpp",
        "EGL/egl_tls.cpp",
        "EGL/egl_cache.cpp",
        "EGL/egl_cache.cpp",
        "EGL/egl_cache_multifile.cpp",
        "EGL/egl_display.cpp",
        "EGL/egl_display.cpp",
        "EGL/egl_object.cpp",
        "EGL/egl_object.cpp",
        "EGL/egl_layers.cpp",
        "EGL/egl_layers.cpp",
@@ -205,6 +205,11 @@ cc_test {
    srcs: [
    srcs: [
        "EGL/BlobCache.cpp",
        "EGL/BlobCache.cpp",
        "EGL/BlobCache_test.cpp",
        "EGL/BlobCache_test.cpp",
        "EGL/MultifileBlobCache.cpp",
        "EGL/MultifileBlobCache_test.cpp",
    ],
    shared_libs: [
        "libutils",
    ],
    ],
}
}


+689 −0

File added.

Preview size limit exceeded, changes collapsed.

+167 −0
Original line number Original line Diff line number Diff line
/*
 ** Copyright 2022, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */

#ifndef ANDROID_MULTIFILE_BLOB_CACHE_H
#define ANDROID_MULTIFILE_BLOB_CACHE_H

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <future>
#include <map>
#include <queue>
#include <string>
#include <thread>
#include <unordered_map>
#include <unordered_set>

namespace android {

struct MultifileHeader {
    EGLsizeiANDROID keySize;
    EGLsizeiANDROID valueSize;
};

struct MultifileEntryStats {
    EGLsizeiANDROID valueSize;
    size_t fileSize;
    time_t accessTime;
};

struct MultifileHotCache {
    int entryFd;
    uint8_t* entryBuffer;
    size_t entrySize;
};

enum class TaskCommand {
    Invalid = 0,
    WriteToDisk,
    Exit,
};

class DeferredTask {
public:
    DeferredTask(TaskCommand command)
          : mCommand(command), mEntryHash(0), mBuffer(nullptr), mBufferSize(0) {}

    TaskCommand getTaskCommand() { return mCommand; }

    void initWriteToDisk(uint32_t entryHash, std::string fullPath, uint8_t* buffer,
                         size_t bufferSize) {
        mCommand = TaskCommand::WriteToDisk;
        mEntryHash = entryHash;
        mFullPath = std::move(fullPath);
        mBuffer = buffer;
        mBufferSize = bufferSize;
    }

    uint32_t getEntryHash() { return mEntryHash; }
    std::string& getFullPath() { return mFullPath; }
    uint8_t* getBuffer() { return mBuffer; }
    size_t getBufferSize() { return mBufferSize; };

private:
    TaskCommand mCommand;

    // Parameters for WriteToDisk
    uint32_t mEntryHash;
    std::string mFullPath;
    uint8_t* mBuffer;
    size_t mBufferSize;
};

class MultifileBlobCache {
public:
    MultifileBlobCache(size_t maxTotalSize, size_t maxHotCacheSize, const std::string& baseDir);
    ~MultifileBlobCache();

    void set(const void* key, EGLsizeiANDROID keySize, const void* value,
             EGLsizeiANDROID valueSize);
    EGLsizeiANDROID get(const void* key, EGLsizeiANDROID keySize, void* value,
                        EGLsizeiANDROID valueSize);

    void finish();

    size_t getTotalSize() const { return mTotalCacheSize; }

private:
    void trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize,
                    time_t accessTime);
    bool contains(uint32_t entryHash) const;
    bool removeEntry(uint32_t entryHash);
    MultifileEntryStats getEntryStats(uint32_t entryHash);

    size_t getFileSize(uint32_t entryHash);
    size_t getValueSize(uint32_t entryHash);

    void increaseTotalCacheSize(size_t fileSize);
    void decreaseTotalCacheSize(size_t fileSize);

    bool addToHotCache(uint32_t entryHash, int fd, uint8_t* entryBufer, size_t entrySize);
    bool removeFromHotCache(uint32_t entryHash);

    void trimCache(size_t cacheByteLimit);
    bool applyLRU(size_t cacheLimit);

    bool mInitialized;
    std::string mMultifileDirName;

    std::unordered_set<uint32_t> mEntries;
    std::unordered_map<uint32_t, MultifileEntryStats> mEntryStats;
    std::unordered_map<uint32_t, MultifileHotCache> mHotCache;

    size_t mMaxKeySize;
    size_t mMaxValueSize;
    size_t mMaxTotalSize;
    size_t mTotalCacheSize;
    size_t mHotCacheLimit;
    size_t mHotCacheEntryLimit;
    size_t mHotCacheSize;

    // Below are the components used for deferred writes

    // Track whether we have pending writes for an entry
    std::multimap<uint32_t, uint8_t*> mDeferredWrites;

    // Functions to work through tasks in the queue
    void processTasks();
    void processTasksImpl(bool* exitThread);
    void processTask(DeferredTask& task);

    // Used by main thread to create work for the worker thread
    void queueTask(DeferredTask&& task);

    // Used by main thread to wait for worker thread to complete all outstanding work.
    void waitForWorkComplete();

    std::thread mTaskThread;
    std::queue<DeferredTask> mTasks;
    std::mutex mWorkerMutex;

    // This condition will block the worker thread until a task is queued
    std::condition_variable mWorkAvailableCondition;

    // This condition will block the main thread while the worker thread still has tasks
    std::condition_variable mWorkerIdleCondition;

    // This bool will track whether all tasks have been completed
    bool mWorkerThreadIdle;
};

}; // namespace android

#endif // ANDROID_MULTIFILE_BLOB_CACHE_H
+200 −0
Original line number Original line Diff line number Diff line
/*
 ** Copyright 2023, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */

#include "MultifileBlobCache.h"

#include <android-base/test_utils.h>
#include <fcntl.h>
#include <gtest/gtest.h>
#include <stdio.h>

#include <memory>

namespace android {

template <typename T>
using sp = std::shared_ptr<T>;

constexpr size_t kMaxTotalSize = 32 * 1024;
constexpr size_t kMaxPreloadSize = 8 * 1024;

constexpr size_t kMaxKeySize = kMaxPreloadSize / 4;
constexpr size_t kMaxValueSize = kMaxPreloadSize / 2;

class MultifileBlobCacheTest : public ::testing::Test {
protected:
    virtual void SetUp() {
        mTempFile.reset(new TemporaryFile());
        mMBC.reset(new MultifileBlobCache(kMaxTotalSize, kMaxPreloadSize, &mTempFile->path[0]));
    }

    virtual void TearDown() { mMBC.reset(); }

    std::unique_ptr<TemporaryFile> mTempFile;
    std::unique_ptr<MultifileBlobCache> mMBC;
};

TEST_F(MultifileBlobCacheTest, CacheSingleValueSucceeds) {
    unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
    mMBC->set("abcd", 4, "efgh", 4);
    ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
    ASSERT_EQ('e', buf[0]);
    ASSERT_EQ('f', buf[1]);
    ASSERT_EQ('g', buf[2]);
    ASSERT_EQ('h', buf[3]);
}

TEST_F(MultifileBlobCacheTest, CacheTwoValuesSucceeds) {
    unsigned char buf[2] = {0xee, 0xee};
    mMBC->set("ab", 2, "cd", 2);
    mMBC->set("ef", 2, "gh", 2);
    ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
    ASSERT_EQ('c', buf[0]);
    ASSERT_EQ('d', buf[1]);
    ASSERT_EQ(size_t(2), mMBC->get("ef", 2, buf, 2));
    ASSERT_EQ('g', buf[0]);
    ASSERT_EQ('h', buf[1]);
}

TEST_F(MultifileBlobCacheTest, GetSetTwiceSucceeds) {
    unsigned char buf[2] = {0xee, 0xee};
    mMBC->set("ab", 2, "cd", 2);
    ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
    ASSERT_EQ('c', buf[0]);
    ASSERT_EQ('d', buf[1]);
    // Use the same key, but different value
    mMBC->set("ab", 2, "ef", 2);
    ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
    ASSERT_EQ('e', buf[0]);
    ASSERT_EQ('f', buf[1]);
}

TEST_F(MultifileBlobCacheTest, GetOnlyWritesInsideBounds) {
    unsigned char buf[6] = {0xee, 0xee, 0xee, 0xee, 0xee, 0xee};
    mMBC->set("abcd", 4, "efgh", 4);
    ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf + 1, 4));
    ASSERT_EQ(0xee, buf[0]);
    ASSERT_EQ('e', buf[1]);
    ASSERT_EQ('f', buf[2]);
    ASSERT_EQ('g', buf[3]);
    ASSERT_EQ('h', buf[4]);
    ASSERT_EQ(0xee, buf[5]);
}

TEST_F(MultifileBlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
    unsigned char buf[3] = {0xee, 0xee, 0xee};
    mMBC->set("abcd", 4, "efgh", 4);
    ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 3));
    ASSERT_EQ(0xee, buf[0]);
    ASSERT_EQ(0xee, buf[1]);
    ASSERT_EQ(0xee, buf[2]);
}

TEST_F(MultifileBlobCacheTest, GetDoesntAccessNullBuffer) {
    mMBC->set("abcd", 4, "efgh", 4);
    ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, nullptr, 0));
}

TEST_F(MultifileBlobCacheTest, MultipleSetsCacheLatestValue) {
    unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
    mMBC->set("abcd", 4, "efgh", 4);
    mMBC->set("abcd", 4, "ijkl", 4);
    ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
    ASSERT_EQ('i', buf[0]);
    ASSERT_EQ('j', buf[1]);
    ASSERT_EQ('k', buf[2]);
    ASSERT_EQ('l', buf[3]);
}

TEST_F(MultifileBlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
    unsigned char buf[kMaxValueSize + 1] = {0xee, 0xee, 0xee, 0xee};
    mMBC->set("abcd", 4, "efgh", 4);
    mMBC->set("abcd", 4, buf, kMaxValueSize + 1);
    ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
    ASSERT_EQ('e', buf[0]);
    ASSERT_EQ('f', buf[1]);
    ASSERT_EQ('g', buf[2]);
    ASSERT_EQ('h', buf[3]);
}

TEST_F(MultifileBlobCacheTest, DoesntCacheIfKeyIsTooBig) {
    char key[kMaxKeySize + 1];
    unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
    for (int i = 0; i < kMaxKeySize + 1; i++) {
        key[i] = 'a';
    }
    mMBC->set(key, kMaxKeySize + 1, "bbbb", 4);
    ASSERT_EQ(size_t(0), mMBC->get(key, kMaxKeySize + 1, buf, 4));
    ASSERT_EQ(0xee, buf[0]);
    ASSERT_EQ(0xee, buf[1]);
    ASSERT_EQ(0xee, buf[2]);
    ASSERT_EQ(0xee, buf[3]);
}

TEST_F(MultifileBlobCacheTest, DoesntCacheIfValueIsTooBig) {
    char buf[kMaxValueSize + 1];
    for (int i = 0; i < kMaxValueSize + 1; i++) {
        buf[i] = 'b';
    }
    mMBC->set("abcd", 4, buf, kMaxValueSize + 1);
    for (int i = 0; i < kMaxValueSize + 1; i++) {
        buf[i] = 0xee;
    }
    ASSERT_EQ(size_t(0), mMBC->get("abcd", 4, buf, kMaxValueSize + 1));
    for (int i = 0; i < kMaxValueSize + 1; i++) {
        SCOPED_TRACE(i);
        ASSERT_EQ(0xee, buf[i]);
    }
}

TEST_F(MultifileBlobCacheTest, CacheMaxKeySizeSucceeds) {
    char key[kMaxKeySize];
    unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
    for (int i = 0; i < kMaxKeySize; i++) {
        key[i] = 'a';
    }
    mMBC->set(key, kMaxKeySize, "wxyz", 4);
    ASSERT_EQ(size_t(4), mMBC->get(key, kMaxKeySize, buf, 4));
    ASSERT_EQ('w', buf[0]);
    ASSERT_EQ('x', buf[1]);
    ASSERT_EQ('y', buf[2]);
    ASSERT_EQ('z', buf[3]);
}

TEST_F(MultifileBlobCacheTest, CacheMaxValueSizeSucceeds) {
    char buf[kMaxValueSize];
    for (int i = 0; i < kMaxValueSize; i++) {
        buf[i] = 'b';
    }
    mMBC->set("abcd", 4, buf, kMaxValueSize);
    for (int i = 0; i < kMaxValueSize; i++) {
        buf[i] = 0xee;
    }
    mMBC->get("abcd", 4, buf, kMaxValueSize);
    for (int i = 0; i < kMaxValueSize; i++) {
        SCOPED_TRACE(i);
        ASSERT_EQ('b', buf[i]);
    }
}

TEST_F(MultifileBlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
    unsigned char buf[1] = {0xee};
    mMBC->set("x", 1, "y", 1);
    ASSERT_EQ(size_t(1), mMBC->get("x", 1, buf, 1));
    ASSERT_EQ('y', buf[0]);
}

} // namespace android
+63 −42
Original line number Original line Diff line number Diff line
@@ -14,6 +14,8 @@
 ** limitations under the License.
 ** limitations under the License.
 */
 */


// #define LOG_NDEBUG 0

#include "egl_cache.h"
#include "egl_cache.h"


#include <android-base/properties.h>
#include <android-base/properties.h>
@@ -25,22 +27,19 @@
#include <thread>
#include <thread>


#include "../egl_impl.h"
#include "../egl_impl.h"
#include "egl_cache_multifile.h"
#include "egl_display.h"
#include "egl_display.h"


// Monolithic cache size limits.
// Monolithic cache size limits.
static const size_t maxKeySize = 12 * 1024;
static const size_t kMaxMonolithicKeySize = 12 * 1024;
static const size_t maxValueSize = 64 * 1024;
static const size_t kMaxMonolithicValueSize = 64 * 1024;
static const size_t maxTotalSize = 32 * 1024 * 1024;
static const size_t kMaxMonolithicTotalSize = 2 * 1024 * 1024;


// The time in seconds to wait before saving newly inserted monolithic cache entries.
// The time in seconds to wait before saving newly inserted monolithic cache entries.
static const unsigned int deferredSaveDelay = 4;
static const unsigned int kDeferredMonolithicSaveDelay = 4;

// Multifile cache size limit
constexpr size_t kMultifileCacheByteLimit = 64 * 1024 * 1024;


// Delay before cleaning up multifile cache entries
// Multifile cache size limits
static const unsigned int deferredMultifileCleanupDelaySeconds = 1;
constexpr uint32_t kMultifileHotCacheLimit = 8 * 1024 * 1024;
constexpr uint32_t kMultifileCacheByteLimit = 32 * 1024 * 1024;


namespace android {
namespace android {


@@ -68,10 +67,7 @@ static EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize, void* v
// egl_cache_t definition
// egl_cache_t definition
//
//
egl_cache_t::egl_cache_t()
egl_cache_t::egl_cache_t()
      : mInitialized(false),
      : mInitialized(false), mMultifileMode(false), mCacheByteLimit(kMaxMonolithicTotalSize) {}
        mMultifileMode(false),
        mCacheByteLimit(maxTotalSize),
        mMultifileCleanupPending(false) {}


egl_cache_t::~egl_cache_t() {}
egl_cache_t::~egl_cache_t() {}


@@ -85,7 +81,7 @@ void egl_cache_t::initialize(egl_display_t* display) {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);


    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
    if (display && cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
        const char* exts = display->disp.queryString.extensions;
        const char* exts = display->disp.queryString.extensions;
        size_t bcExtLen = strlen(BC_EXT_STR);
        size_t bcExtLen = strlen(BC_EXT_STR);
        size_t extsLen = strlen(exts);
        size_t extsLen = strlen(exts);
@@ -114,14 +110,36 @@ void egl_cache_t::initialize(egl_display_t* display) {
        }
        }
    }
    }


    // Allow forcing monolithic cache for debug purposes
    // Check the device config to decide whether multifile should be used
    if (base::GetProperty("debug.egl.blobcache.multifilemode", "") == "false") {
    if (base::GetBoolProperty("ro.egl.blobcache.multifile", false)) {
        ALOGD("Forcing monolithic cache due to debug.egl.blobcache.multifilemode == \"false\"");
        mMultifileMode = true;
        ALOGV("Using multifile EGL blobcache");
    }

    // Allow forcing the mode for debug purposes
    std::string mode = base::GetProperty("debug.egl.blobcache.multifile", "");
    if (mode == "true") {
        ALOGV("Forcing multifile cache due to debug.egl.blobcache.multifile == %s", mode.c_str());
        mMultifileMode = true;
    } else if (mode == "false") {
        ALOGV("Forcing monolithic cache due to debug.egl.blobcache.multifile == %s", mode.c_str());
        mMultifileMode = false;
        mMultifileMode = false;
    }
    }


    if (mMultifileMode) {
    if (mMultifileMode) {
        mCacheByteLimit = kMultifileCacheByteLimit;
        mCacheByteLimit = static_cast<size_t>(
                base::GetUintProperty<uint32_t>("ro.egl.blobcache.multifile_limit",
                                                kMultifileCacheByteLimit));

        // Check for a debug value
        int debugCacheSize = base::GetIntProperty("debug.egl.blobcache.multifile_limit", -1);
        if (debugCacheSize >= 0) {
            ALOGV("Overriding cache limit %zu with %i from debug.egl.blobcache.multifile_limit",
                  mCacheByteLimit, debugCacheSize);
            mCacheByteLimit = debugCacheSize;
        }

        ALOGV("Using multifile EGL blobcache limit of %zu bytes", mCacheByteLimit);
    }
    }


    mInitialized = true;
    mInitialized = true;
@@ -133,10 +151,10 @@ void egl_cache_t::terminate() {
        mBlobCache->writeToFile();
        mBlobCache->writeToFile();
    }
    }
    mBlobCache = nullptr;
    mBlobCache = nullptr;
    if (mMultifileMode) {
    if (mMultifileBlobCache) {
        checkMultifileCacheSize(mCacheByteLimit);
        mMultifileBlobCache->finish();
    }
    }
    mMultifileMode = false;
    mMultifileBlobCache = nullptr;
    mInitialized = false;
    mInitialized = false;
}
}


@@ -151,20 +169,8 @@ void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, const void*


    if (mInitialized) {
    if (mInitialized) {
        if (mMultifileMode) {
        if (mMultifileMode) {
            setBlobMultifile(key, keySize, value, valueSize, mFilename);
            MultifileBlobCache* mbc = getMultifileBlobCacheLocked();

            mbc->set(key, keySize, value, valueSize);
            if (!mMultifileCleanupPending) {
                mMultifileCleanupPending = true;
                // Kick off a thread to cull cache files below limit
                std::thread deferredMultifileCleanupThread([this]() {
                    sleep(deferredMultifileCleanupDelaySeconds);
                    std::lock_guard<std::mutex> lock(mMutex);
                    // Check the size of cache and remove entries to stay under limit
                    checkMultifileCacheSize(mCacheByteLimit);
                    mMultifileCleanupPending = false;
                });
                deferredMultifileCleanupThread.detach();
            }
        } else {
        } else {
            BlobCache* bc = getBlobCacheLocked();
            BlobCache* bc = getBlobCacheLocked();
            bc->set(key, keySize, value, valueSize);
            bc->set(key, keySize, value, valueSize);
@@ -172,7 +178,7 @@ void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, const void*
            if (!mSavePending) {
            if (!mSavePending) {
                mSavePending = true;
                mSavePending = true;
                std::thread deferredSaveThread([this]() {
                std::thread deferredSaveThread([this]() {
                    sleep(deferredSaveDelay);
                    sleep(kDeferredMonolithicSaveDelay);
                    std::lock_guard<std::mutex> lock(mMutex);
                    std::lock_guard<std::mutex> lock(mMutex);
                    if (mInitialized && mBlobCache) {
                    if (mInitialized && mBlobCache) {
                        mBlobCache->writeToFile();
                        mBlobCache->writeToFile();
@@ -196,15 +202,21 @@ EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize, v


    if (mInitialized) {
    if (mInitialized) {
        if (mMultifileMode) {
        if (mMultifileMode) {
            return getBlobMultifile(key, keySize, value, valueSize, mFilename);
            MultifileBlobCache* mbc = getMultifileBlobCacheLocked();
            return mbc->get(key, keySize, value, valueSize);
        } else {
        } else {
            BlobCache* bc = getBlobCacheLocked();
            BlobCache* bc = getBlobCacheLocked();
            return bc->get(key, keySize, value, valueSize);
            return bc->get(key, keySize, value, valueSize);
        }
        }
    }
    }

    return 0;
    return 0;
}
}


void egl_cache_t::setCacheMode(EGLCacheMode cacheMode) {
    mMultifileMode = (cacheMode == EGLCacheMode::Multifile);
}

void egl_cache_t::setCacheFilename(const char* filename) {
void egl_cache_t::setCacheFilename(const char* filename) {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    mFilename = filename;
    mFilename = filename;
@@ -216,7 +228,7 @@ void egl_cache_t::setCacheLimit(int64_t cacheByteLimit) {
    if (!mMultifileMode) {
    if (!mMultifileMode) {
        // If we're not in multifile mode, ensure the cache limit is only being lowered,
        // If we're not in multifile mode, ensure the cache limit is only being lowered,
        // not increasing above the hard coded platform limit
        // not increasing above the hard coded platform limit
        if (cacheByteLimit > maxTotalSize) {
        if (cacheByteLimit > kMaxMonolithicTotalSize) {
            return;
            return;
        }
        }
    }
    }
@@ -226,8 +238,8 @@ void egl_cache_t::setCacheLimit(int64_t cacheByteLimit) {


size_t egl_cache_t::getCacheSize() {
size_t egl_cache_t::getCacheSize() {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    if (mMultifileMode) {
    if (mMultifileBlobCache) {
        return getMultifileCacheSize();
        return mMultifileBlobCache->getTotalSize();
    }
    }
    if (mBlobCache) {
    if (mBlobCache) {
        return mBlobCache->getSize();
        return mBlobCache->getSize();
@@ -237,9 +249,18 @@ size_t egl_cache_t::getCacheSize() {


BlobCache* egl_cache_t::getBlobCacheLocked() {
BlobCache* egl_cache_t::getBlobCacheLocked() {
    if (mBlobCache == nullptr) {
    if (mBlobCache == nullptr) {
        mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, mCacheByteLimit, mFilename));
        mBlobCache.reset(new FileBlobCache(kMaxMonolithicKeySize, kMaxMonolithicValueSize,
                                           mCacheByteLimit, mFilename));
    }
    }
    return mBlobCache.get();
    return mBlobCache.get();
}
}


MultifileBlobCache* egl_cache_t::getMultifileBlobCacheLocked() {
    if (mMultifileBlobCache == nullptr) {
        mMultifileBlobCache.reset(
                new MultifileBlobCache(mCacheByteLimit, kMultifileHotCacheLimit, mFilename));
    }
    return mMultifileBlobCache.get();
}

}; // namespace android
}; // namespace android
Loading