EGL: add deferred saving of the cache

This change causes any insertions into the EGL cache to trigger an
attempt to save the cache contents to disk.  The save operation is
deferred to allow multiple cache insertions to be batched up.

Change-Id: I6cfec9c0dbbef94d3f8880860e2a365dccc296c7
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index aa40d58..522421b 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -34,6 +34,9 @@
 static const char* cacheFileMagic = "EGL$";
 static const size_t cacheFileHeaderSize = 8;
 
+// The time in seconds to wait before saving newly inserted cache entries.
+static const unsigned int deferredSaveDelay = 4;
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -128,6 +131,30 @@
     if (mInitialized) {
         sp<BlobCache> bc = getBlobCacheLocked();
         bc->set(key, keySize, value, valueSize);
+
+        if (!mSavePending) {
+            class DeferredSaveThread : public Thread {
+            public:
+                DeferredSaveThread() : Thread(false) {}
+
+                virtual bool threadLoop() {
+                    sleep(deferredSaveDelay);
+                    egl_cache_t* c = egl_cache_t::get();
+                    Mutex::Autolock lock(c->mMutex);
+                    if (c->mInitialized) {
+                        c->saveBlobCacheLocked();
+                    }
+                    c->mSavePending = false;
+                    return false;
+                }
+            };
+
+            // The thread will hold a strong ref to itself until it has finished
+            // running, so there's no need to keep a ref around.
+            sp<Thread> deferredSaveThread(new DeferredSaveThread());
+            mSavePending = true;
+            deferredSaveThread->run();
+        }
     }
 }