SF: RenderEngine::primeCache should not be called as SCHED_FIFO

RenderEngine::primeCache is quite long and as such can't run at
SCHED_FIFO.

Test: boot the device and observe RenderEngine::primeCache timing
Bug: 190529454
Change-Id: I9024c4a365efde717bd4cc9f382d1729a2e2446f
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 3c58238..18eb7b5 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -515,9 +515,10 @@
     return mDrawingBuffer.get();
 }
 
-void GLESRenderEngine::primeCache() {
+std::future<void> GLESRenderEngine::primeCache() {
     ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
                                            mUseColorManagement, mPrecacheToneMapperShaderOnly);
+    return {};
 }
 
 base::unique_fd GLESRenderEngine::flush() {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index e7ed9c0..1ff3674 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -57,7 +57,7 @@
                      EGLSurface protectedStub);
     ~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
 
-    void primeCache() override;
+    std::future<void> primeCache() override;
     void genTextures(size_t count, uint32_t* names) override;
     void deleteTextures(size_t count, uint32_t const* names) override;
     bool isProtected() const override { return mInProtectedContext; }
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index d1bbcc5..67c3721 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -29,6 +29,7 @@
 #include <ui/GraphicTypes.h>
 #include <ui/Transform.h>
 
+#include <future>
 #include <memory>
 
 /**
@@ -104,7 +105,7 @@
     // This interface, while still in use until a suitable replacement is built,
     // should be considered deprecated, minus some methods which still may be
     // used to support legacy behavior.
-    virtual void primeCache() = 0;
+    virtual std::future<void> primeCache() = 0;
 
     // dump the extension strings. always call the base class.
     virtual void dump(std::string& result) = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 27dbd1e..baa1305 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -35,7 +35,7 @@
     RenderEngine();
     ~RenderEngine() override;
 
-    MOCK_METHOD0(primeCache, void());
+    MOCK_METHOD0(primeCache, std::future<void>());
     MOCK_METHOD1(dump, void(std::string&));
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 2d80c46..28d098c 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -234,8 +234,9 @@
     return engine;
 }
 
-void SkiaGLRenderEngine::primeCache() {
+std::future<void> SkiaGLRenderEngine::primeCache() {
     Cache::primeShaderCache(this);
+    return {};
 }
 
 EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 97d3b72..145f2dd 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -53,7 +53,7 @@
                        EGLSurface protectedPlaceholder);
     ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex);
 
-    void primeCache() override;
+    std::future<void> primeCache() override;
     status_t drawLayers(const DisplaySettings& display,
                         const std::vector<const LayerSettings*>& layers,
                         const std::shared_ptr<ExternalTexture>& buffer,
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 308c5ff..4cda133 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -39,7 +39,7 @@
     SkiaRenderEngine(RenderEngineType type) : RenderEngine(type) {}
     ~SkiaRenderEngine() override {}
 
-    virtual void primeCache() override{};
+    virtual std::future<void> primeCache() override { return {}; };
     virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{};
     virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{};
     virtual bool isProtected() const override { return false; } // mInProtectedContext; }
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 9009ce4..6f96bae 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -59,14 +59,32 @@
     }
 }
 
+status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
+    static constexpr int kFifoPriority = 2;
+    static constexpr int kOtherPriority = 0;
+
+    struct sched_param param = {0};
+    int sched_policy;
+    if (enabled) {
+        sched_policy = SCHED_FIFO;
+        param.sched_priority = kFifoPriority;
+    } else {
+        sched_policy = SCHED_OTHER;
+        param.sched_priority = kOtherPriority;
+    }
+
+    if (sched_setscheduler(0, sched_policy, &param) != 0) {
+        return -errno;
+    }
+    return NO_ERROR;
+}
+
 // NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
 void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
     ATRACE_CALL();
 
-    struct sched_param param = {0};
-    param.sched_priority = 2;
-    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
-        ALOGE("Couldn't set SCHED_FIFO");
+    if (setSchedFifo(true) != NO_ERROR) {
+        ALOGW("Couldn't set SCHED_FIFO");
     }
 
     mRenderEngine = factory();
@@ -100,18 +118,31 @@
     mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
 }
 
-void RenderEngineThreaded::primeCache() {
+std::future<void> RenderEngineThreaded::primeCache() {
+    const auto resultPromise = std::make_shared<std::promise<void>>();
+    std::future<void> resultFuture = resultPromise->get_future();
     ATRACE_CALL();
     // This function is designed so it can run asynchronously, so we do not need to wait
     // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::primeCache");
+            if (setSchedFifo(false) != NO_ERROR) {
+                ALOGW("Couldn't set SCHED_OTHER for primeCache");
+            }
+
             instance.primeCache();
+            resultPromise->set_value();
+
+            if (setSchedFifo(true) != NO_ERROR) {
+                ALOGW("Couldn't set SCHED_FIFO for primeCache");
+            }
         });
     }
     mCondition.notify_one();
+
+    return resultFuture;
 }
 
 void RenderEngineThreaded::dump(std::string& result) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index eb6098e..76b9016 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -42,7 +42,7 @@
 
     RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type);
     ~RenderEngineThreaded() override;
-    void primeCache() override;
+    std::future<void> primeCache() override;
 
     void dump(std::string& result) override;
 
@@ -74,6 +74,7 @@
 private:
     void threadMain(CreateInstanceFactory factory);
     void waitUntilInitialized() const;
+    static status_t setSchedFifo(bool enabled);
 
     /* ------------------------------------------------------------------------
      * Threading
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a4b6fef..9cccd69 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -680,6 +680,10 @@
     if (mStartPropertySetThread->join() != NO_ERROR) {
         ALOGE("Join StartPropertySetThread failed!");
     }
+
+    if (mRenderEnginePrimeCacheFuture.valid()) {
+        mRenderEnginePrimeCacheFuture.get();
+    }
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
     ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
@@ -807,7 +811,15 @@
     char primeShaderCache[PROPERTY_VALUE_MAX];
     property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
     if (atoi(primeShaderCache)) {
-        getRenderEngine().primeCache();
+        if (setSchedFifo(false) != NO_ERROR) {
+            ALOGW("Can't set SCHED_OTHER for primeCache");
+        }
+
+        mRenderEnginePrimeCacheFuture = getRenderEngine().primeCache();
+
+        if (setSchedFifo(true) != NO_ERROR) {
+            ALOGW("Can't set SCHED_OTHER for primeCache");
+        }
     }
 
     getRenderEngine().onPrimaryDisplaySizeChanged(display->getSize());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 519a5ab..a3fa8d6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1183,6 +1183,8 @@
     sp<StartPropertySetThread> mStartPropertySetThread;
     surfaceflinger::Factory& mFactory;
 
+    std::future<void> mRenderEnginePrimeCacheFuture;
+
     // access must be protected by mStateLock
     mutable Mutex mStateLock;
     State mCurrentState{LayerVector::StateSet::Current};