EGL Multifile Blobcache: Remove entries when valueSize is zero

When set is called with a value size of zero, the cache will simply remove
the entry from disk and return.

Any pending writes will complete before the entry is removed.

Additional tests:
* ZeroSizeRemovesEntry

Based on work by: Igor Nazarov <i.nazarov@samsung.com>

Test: libEGL_test, EGL_test, ANGLE trace tests, apps
Bug: b/355259618, b/380483358
Flag: com.android.graphics.egl.flags.multifile_blobcache_advanced_usage
Change-Id: I092a0e41c587ac036311b5e08e8b6ffa59588bca
diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp
index 1f6d4d0..04c525e 100644
--- a/opengl/libs/EGL/MultifileBlobCache.cpp
+++ b/opengl/libs/EGL/MultifileBlobCache.cpp
@@ -330,6 +330,8 @@
     // Generate a hash of the key and use it to track this entry
     uint32_t entryHash = android::JenkinsHashMixBytes(0, static_cast<const uint8_t*>(key), keySize);
 
+    std::string fullPath = mMultifileDirName + "/" + std::to_string(entryHash);
+
     // See if we already have this file
     if (flags::multifile_blobcache_advanced_usage() && contains(entryHash)) {
         // Remove previous entry from hot cache
@@ -337,6 +339,17 @@
 
         // Remove previous entry and update the overall cache size
         removeEntry(entryHash);
+
+        // If valueSize is zero, this is an indication that the user wants to remove the entry from
+        // cache It has already been removed from tracking, now remove it from disk It is safe to do
+        // this immediately because we drained the write queue in removeFromHotCache
+        if (valueSize == 0) {
+            ALOGV("SET: Zero size detected for existing entry, removing %u from cache", entryHash);
+            if (remove(fullPath.c_str()) != 0) {
+                ALOGW("SET: Error removing %s: %s", fullPath.c_str(), std::strerror(errno));
+            }
+            return;
+        }
     }
 
     size_t fileSize = sizeof(MultifileHeader) + keySize + valueSize;
@@ -361,8 +374,6 @@
     memcpy(static_cast<void*>(buffer + sizeof(MultifileHeader) + keySize),
            static_cast<const void*>(value), valueSize);
 
-    std::string fullPath = mMultifileDirName + "/" + std::to_string(entryHash);
-
     // Track the size and access time for quick recall and update the overall cache size
     struct timespec time = {0, 0};
     if (flags::multifile_blobcache_advanced_usage()) {