Merge changes from topic "scheduler::123998711"

* changes:
  SF: Adding testable Scheduler and updating tests.
  SF: Migrate to Scheduler and clean up duplicate code.
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 61745b5..2a28627 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -113,6 +113,7 @@
 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
+#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
 #define WLUTIL "/vendor/xbin/wlutil"
 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
 
@@ -1455,9 +1456,12 @@
     add_mountinfo();
     DumpIpTablesAsRoot();
 
-    // Capture any IPSec policies in play.  No keys are exposed here.
+    // Capture any IPSec policies in play. No keys are exposed here.
     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
 
+    // Dump IPsec stats. No keys are exposed here.
+    DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
+
     // Run ss as root so we can see socket marks.
     RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
 
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 75fe2d3..a07627a 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -157,10 +157,11 @@
 }
 
 void GraphicsEnv::setGpuStats(const std::string& driverPackageName,
-                              const std::string& driverVersionName,
-                              const uint64_t driverVersionCode, const std::string& appPackageName) {
+                              const std::string& driverVersionName, uint64_t driverVersionCode,
+                              const std::string& appPackageName) {
     ATRACE_CALL();
 
+    std::lock_guard<std::mutex> lock(mStatsLock);
     ALOGV("setGpuStats:\n"
           "\tdriverPackageName[%s]\n"
           "\tdriverVersionName[%s]\n"
@@ -169,15 +170,89 @@
           driverPackageName.c_str(), driverVersionName.c_str(),
           (unsigned long long)driverVersionCode, appPackageName.c_str());
 
-    mGpuStats = {
-            .driverPackageName = driverPackageName,
-            .driverVersionName = driverVersionName,
-            .driverVersionCode = driverVersionCode,
-            .appPackageName = appPackageName,
-    };
+    mGpuStats.driverPackageName = driverPackageName;
+    mGpuStats.driverVersionName = driverVersionName;
+    mGpuStats.driverVersionCode = driverVersionCode;
+    mGpuStats.appPackageName = appPackageName;
 }
 
-void GraphicsEnv::sendGpuStats() {
+void GraphicsEnv::setDriverToLoad(GraphicsEnv::Driver driver) {
+    ATRACE_CALL();
+
+    std::lock_guard<std::mutex> lock(mStatsLock);
+    switch (driver) {
+        case GraphicsEnv::Driver::GL:
+        case GraphicsEnv::Driver::GL_UPDATED:
+        case GraphicsEnv::Driver::ANGLE: {
+            if (mGpuStats.glDriverToLoad == GraphicsEnv::Driver::NONE) {
+                mGpuStats.glDriverToLoad = driver;
+                break;
+            }
+
+            if (mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) {
+                mGpuStats.glDriverFallback = driver;
+            }
+            break;
+        }
+        case Driver::VULKAN:
+        case Driver::VULKAN_UPDATED: {
+            if (mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::NONE) {
+                mGpuStats.vkDriverToLoad = driver;
+                break;
+            }
+
+            if (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE) {
+                mGpuStats.vkDriverFallback = driver;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+void GraphicsEnv::setDriverLoaded(GraphicsEnv::Api api, bool isLoaded, int64_t driverLoadingTime) {
+    ATRACE_CALL();
+
+    std::lock_guard<std::mutex> lock(mStatsLock);
+    GraphicsEnv::Driver driver = GraphicsEnv::Driver::NONE;
+    bool isIntendedDriverLoaded = false;
+    if (api == GraphicsEnv::Api::API_GL) {
+        driver = mGpuStats.glDriverToLoad;
+        isIntendedDriverLoaded = isLoaded &&
+                ((mGpuStats.glDriverFallback == GraphicsEnv::Driver::NONE) ||
+                 (mGpuStats.glDriverToLoad == mGpuStats.glDriverFallback));
+    } else {
+        driver = mGpuStats.vkDriverToLoad;
+        isIntendedDriverLoaded =
+                isLoaded && (mGpuStats.vkDriverFallback == GraphicsEnv::Driver::NONE);
+    }
+
+    sendGpuStatsLocked(driver, isIntendedDriverLoaded, driverLoadingTime);
+}
+
+void GraphicsEnv::clearDriverLoadingInfo(GraphicsEnv::Api api) {
+    ATRACE_CALL();
+
+    std::lock_guard<std::mutex> lock(mStatsLock);
+    if (api == GraphicsEnv::Api::API_GL) {
+        mGpuStats.glDriverToLoad = GraphicsEnv::Driver::NONE;
+        mGpuStats.glDriverFallback = GraphicsEnv::Driver::NONE;
+    }
+}
+
+static sp<IGpuService> getGpuService() {
+    const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
+    if (!binder) {
+        ALOGE("Failed to get gpu service");
+        return nullptr;
+    }
+
+    return interface_cast<IGpuService>(binder);
+}
+
+void GraphicsEnv::sendGpuStatsLocked(GraphicsEnv::Driver driver, bool isDriverLoaded,
+                                     int64_t driverLoadingTime) {
     ATRACE_CALL();
 
     // Do not sendGpuStats for those skipping the GraphicsEnvironment setup
@@ -187,20 +262,20 @@
           "\tdriverPackageName[%s]\n"
           "\tdriverVersionName[%s]\n"
           "\tdriverVersionCode[%llu]\n"
-          "\tappPackageName[%s]\n",
+          "\tappPackageName[%s]\n"
+          "\tdriver[%d]\n"
+          "\tisDriverLoaded[%d]\n"
+          "\tdriverLoadingTime[%lld]",
           mGpuStats.driverPackageName.c_str(), mGpuStats.driverVersionName.c_str(),
-          (unsigned long long)mGpuStats.driverVersionCode, mGpuStats.appPackageName.c_str());
+          (unsigned long long)mGpuStats.driverVersionCode, mGpuStats.appPackageName.c_str(),
+          static_cast<int32_t>(driver), isDriverLoaded, (long long)driverLoadingTime);
 
-    const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
-    if (!binder) {
-        ALOGE("Failed to get gpu service for [%s]", mGpuStats.appPackageName.c_str());
-        return;
+    const sp<IGpuService> gpuService = getGpuService();
+    if (gpuService) {
+        gpuService->setGpuStats(mGpuStats.driverPackageName, mGpuStats.driverVersionName,
+                                mGpuStats.driverVersionCode, mGpuStats.appPackageName, driver,
+                                isDriverLoaded, driverLoadingTime);
     }
-
-    interface_cast<IGpuService>(binder)->setGpuStats(mGpuStats.driverPackageName,
-                                                     mGpuStats.driverVersionName,
-                                                     mGpuStats.driverVersionCode,
-                                                     mGpuStats.appPackageName);
 }
 
 void* GraphicsEnv::loadLibrary(std::string name) {
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 762a27b..2a57caf 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -28,8 +28,9 @@
     explicit BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
 
     virtual void setGpuStats(const std::string& driverPackageName,
-                             const std::string& driverVersionName, const uint64_t driverVersionCode,
-                             const std::string& appPackageName) {
+                             const std::string& driverVersionName, uint64_t driverVersionCode,
+                             const std::string& appPackageName, GraphicsEnv::Driver driver,
+                             bool isDriverLoaded, int64_t driverLoadingTime) {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
 
@@ -37,6 +38,9 @@
         data.writeUtf8AsUtf16(driverVersionName);
         data.writeUint64(driverVersionCode);
         data.writeUtf8AsUtf16(appPackageName);
+        data.writeInt32(static_cast<int32_t>(driver));
+        data.writeBool(isDriverLoaded);
+        data.writeInt64(driverLoadingTime);
 
         remote()->transact(BnGpuService::SET_GPU_STATS, data, &reply);
     }
@@ -65,7 +69,18 @@
             std::string appPackageName;
             if ((status = data.readUtf8FromUtf16(&appPackageName)) != OK) return status;
 
-            setGpuStats(driverPackageName, driverVersionName, driverVersionCode, appPackageName);
+            int32_t driver;
+            if ((status = data.readInt32(&driver)) != OK) return status;
+
+            bool isDriverLoaded;
+            if ((status = data.readBool(&isDriverLoaded)) != OK) return status;
+
+            int64_t driverLoadingTime;
+            if ((status = data.readInt64(&driverLoadingTime)) != OK) return status;
+
+            setGpuStats(driverPackageName, driverVersionName, driverVersionCode, appPackageName,
+                        static_cast<GraphicsEnv::Driver>(driver), isDriverLoaded,
+                        driverLoadingTime);
 
             return OK;
         }
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index c4482b7..d88a5c1 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -28,11 +28,41 @@
 struct NativeLoaderNamespace;
 
 class GraphicsEnv {
+public:
+    enum Api {
+        API_GL = 0,
+        API_VK = 1,
+    };
+
+    enum Driver {
+        NONE = 0,
+        GL = 1,
+        GL_UPDATED = 2,
+        VULKAN = 3,
+        VULKAN_UPDATED = 4,
+        ANGLE = 5,
+    };
+
+private:
     struct GpuStats {
         std::string driverPackageName;
         std::string driverVersionName;
         uint64_t driverVersionCode;
         std::string appPackageName;
+        Driver glDriverToLoad;
+        Driver glDriverFallback;
+        Driver vkDriverToLoad;
+        Driver vkDriverFallback;
+
+        GpuStats()
+              : driverPackageName(""),
+                driverVersionName(""),
+                driverVersionCode(0),
+                appPackageName(""),
+                glDriverToLoad(Driver::NONE),
+                glDriverFallback(Driver::NONE),
+                vkDriverToLoad(Driver::NONE),
+                vkDriverFallback(Driver::NONE) {}
     };
 
 public:
@@ -48,8 +78,11 @@
     void setDriverPath(const std::string path);
     android_namespace_t* getDriverNamespace();
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
-                     const uint64_t versionCode, const std::string& appPackageName);
-    void sendGpuStats();
+                     uint64_t versionCode, const std::string& appPackageName);
+    void setDriverToLoad(Driver driver);
+    void setDriverLoaded(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
+    void clearDriverLoadingInfo(Api api);
+    void sendGpuStatsLocked(Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
 
     bool shouldUseAngle(std::string appName);
     bool shouldUseAngle();
@@ -82,6 +115,7 @@
 
     GraphicsEnv() = default;
     std::string mDriverPath;
+    std::mutex mStatsLock;
     GpuStats mGpuStats;
     std::string mAnglePath;
     std::string mAngleAppName;
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 1e74d60..bfde76f 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -18,6 +18,7 @@
 
 #include <binder/IInterface.h>
 #include <cutils/compiler.h>
+#include <graphicsenv/GraphicsEnv.h>
 
 #include <vector>
 
@@ -29,12 +30,13 @@
  */
 class IGpuService : public IInterface {
 public:
-    DECLARE_META_INTERFACE(GpuService);
+    DECLARE_META_INTERFACE(GpuService)
 
     // set GPU stats from GraphicsEnvironment.
     virtual void setGpuStats(const std::string& driverPackageName,
-                             const std::string& driverVersionName, const uint64_t driverVersionCode,
-                             const std::string& appPackageName) = 0;
+                             const std::string& driverVersionName, uint64_t driverVersionCode,
+                             const std::string& appPackageName, GraphicsEnv::Driver driver,
+                             bool isDriverLoaded, int64_t driverLoadingTime) = 0;
 };
 
 class BnGpuService : public BnInterface<IGpuService> {
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 4cafe2b..259242b 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -27,6 +27,7 @@
 #include <android/dlext.h>
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <utils/Timers.h>
 
 #ifndef __ANDROID_VNDK__
 #include <graphicsenv/GraphicsEnv.h>
@@ -217,6 +218,7 @@
 void* Loader::open(egl_connection_t* cnx)
 {
     ATRACE_CALL();
+    const nsecs_t openTime = systemTime();
 
     void* dso;
     driver_t* hnd = nullptr;
@@ -234,6 +236,8 @@
     if (dso) {
         hnd = new driver_t(dso);
     } else {
+        android::GraphicsEnv::getInstance().clearDriverLoadingInfo(
+                android::GraphicsEnv::Api::API_GL);
         // Always load EGL first
         dso = load_driver("EGL", cnx, EGL);
         if (dso) {
@@ -243,19 +247,30 @@
         }
     }
 
+    if (!hnd) {
+        android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+                                                            false, systemTime() - openTime);
+    }
+
     LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
 
     cnx->libEgl   = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
     cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
     cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
 
+    if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
+        android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
+                                                            false, systemTime() - openTime);
+    }
+
     LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
             "couldn't load system EGL wrapper libraries");
 
     LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
             "couldn't load system OpenGL ES wrapper libraries");
 
-    android::GraphicsEnv::getInstance().sendGpuStats();
+    android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, true,
+                                                        systemTime() - openTime);
 
     return (void*)hnd;
 }
@@ -591,17 +606,21 @@
     void* dso = nullptr;
     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
     if (ns) {
+        android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE);
         dso = load_angle(kind, ns, cnx);
     }
 #ifndef __ANDROID_VNDK__
     if (!dso) {
         android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
         if (ns) {
+            android::GraphicsEnv::getInstance().setDriverToLoad(
+                    android::GraphicsEnv::Driver::GL_UPDATED);
             dso = load_updated_driver(kind, ns);
         }
     }
 #endif
     if (!dso) {
+        android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
         dso = load_system_driver(kind);
         if (!dso)
             return nullptr;
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 68c185c..8a9778a 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -38,8 +38,9 @@
 GpuService::GpuService() = default;
 
 void GpuService::setGpuStats(const std::string& driverPackageName,
-                             const std::string& driverVersionName, const uint64_t driverVersionCode,
-                             const std::string& appPackageName) {
+                             const std::string& driverVersionName, uint64_t driverVersionCode,
+                             const std::string& appPackageName, GraphicsEnv::Driver driver,
+                             bool isDriverLoaded, int64_t driverLoadingTime) {
     ATRACE_CALL();
 
     std::lock_guard<std::mutex> lock(mStateLock);
@@ -47,9 +48,13 @@
           "\tdriverPackageName[%s]\n"
           "\tdriverVersionName[%s]\n"
           "\tdriverVersionCode[%llu]\n"
-          "\tappPackageName[%s]\n",
+          "\tappPackageName[%s]\n"
+          "\tdriver[%d]\n"
+          "\tisDriverLoaded[%d]\n"
+          "\tdriverLoadingTime[%lld]",
           driverPackageName.c_str(), driverVersionName.c_str(),
-          (unsigned long long)driverVersionCode, appPackageName.c_str());
+          (unsigned long long)driverVersionCode, appPackageName.c_str(),
+          static_cast<int32_t>(driver), isDriverLoaded, (long long)driverLoadingTime);
 }
 
 status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 5304fa1..2756557 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -38,7 +38,8 @@
 private:
     // IGpuService interface
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
-                     const uint64_t driverVersionCode, const std::string& appPackageName);
+                     uint64_t driverVersionCode, const std::string& appPackageName,
+                     GraphicsEnv::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
 
     // GpuStats access must be protected by mStateLock
     std::mutex mStateLock;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index c077b68..b4952aa 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -380,8 +380,7 @@
     return true;
 }
 
-bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                              const sp<Fence>& releaseFence) {
+bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
     ATRACE_CALL();
 
     bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
@@ -420,7 +419,7 @@
         return false;
     }
 
-    status_t err = updateTexImage(recomputeVisibleRegions, latchTime, releaseFence);
+    status_t err = updateTexImage(recomputeVisibleRegions, latchTime);
     if (err != NO_ERROR) {
         return false;
     }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index d358bae..e3b10fc 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -93,11 +93,7 @@
     // the visible regions need to be recomputed (this is a fairly heavy
     // operation, so this should be set only if needed). Typically this is used
     // to figure out if the content or size of a surface has changed.
-    // If there was a GL composition step rendering the previous frame, then
-    // releaseFence will be populated with a native fence that fires when
-    // composition has completed.
-    bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                     const sp<Fence>& releaseFence) override;
+    bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
 
     bool isBufferLatched() const override { return mRefreshPending; }
 
@@ -142,8 +138,7 @@
     virtual void setFilteringEnabled(bool enabled) = 0;
 
     virtual status_t bindTextureImage() = 0;
-    virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                                    const sp<Fence>& flushFence) = 0;
+    virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
 
     virtual status_t updateActiveBuffer() = 0;
     virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 7ed8184..6866e5c 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -100,8 +100,7 @@
 
 status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
                                              bool* autoRefresh, bool* queuedBuffer,
-                                             uint64_t maxFrameNumber,
-                                             const sp<Fence>& releaseFence) {
+                                             uint64_t maxFrameNumber) {
     ATRACE_CALL();
     BLC_LOGV("updateTexImage");
     Mutex::Autolock lock(mMutex);
@@ -146,7 +145,7 @@
     }
 
     // Release the previous buffer.
-    err = updateAndReleaseLocked(item, &mPendingRelease, releaseFence);
+    err = updateAndReleaseLocked(item, &mPendingRelease);
     if (err != NO_ERROR) {
         return err;
     }
@@ -224,25 +223,11 @@
 }
 
 status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
-                                                     PendingRelease* pendingRelease,
-                                                     const sp<Fence>& releaseFence) {
+                                                     PendingRelease* pendingRelease) {
     status_t err = NO_ERROR;
 
     int slot = item.mSlot;
 
-    // Do whatever sync ops we need to do before releasing the old slot.
-    if (slot != mCurrentTexture) {
-        err = syncForReleaseLocked(releaseFence);
-        if (err != NO_ERROR) {
-            // Release the buffer we just acquired.  It's not safe to
-            // release the old buffer, so instead we just drop the new frame.
-            // As we are still under lock since acquireBuffer, it is safe to
-            // release by slot.
-            releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
-            return err;
-        }
-    }
-
     BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
              mCurrentTextureBuffer != nullptr ? mCurrentTextureBuffer->handle : 0, slot,
              mSlots[slot].mGraphicBuffer->handle);
@@ -298,30 +283,6 @@
     return mRE.bindExternalTextureBuffer(mTexName, mCurrentTextureBuffer, mCurrentFence, false);
 }
 
-status_t BufferLayerConsumer::syncForReleaseLocked(const sp<Fence>& releaseFence) {
-    BLC_LOGV("syncForReleaseLocked");
-
-    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        if (mRE.useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
-            // TODO(alecmouri): fail further upstream if the fence is invalid
-            if (!releaseFence->isValid()) {
-                BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
-                return UNKNOWN_ERROR;
-            }
-            status_t err =
-                    addReleaseFenceLocked(mCurrentTexture, mCurrentTextureBuffer, releaseFence);
-            if (err != OK) {
-                BLC_LOGE("syncForReleaseLocked: error adding release fence: "
-                         "%s (%d)",
-                         strerror(-err), err);
-                return err;
-            }
-        }
-    }
-
-    return OK;
-}
-
 void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
     Mutex::Autolock lock(mMutex);
     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index e2ef399..e2a6d2e 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -92,8 +92,7 @@
     // used to reject the newly acquired buffer.  It also does not bind the
     // RenderEngine texture until bindTextureImage is called.
     status_t updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
-                            bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber,
-                            const sp<Fence>& releaseFence);
+                            bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber);
 
     // See BufferLayerConsumer::bindTextureImageLocked().
     status_t bindTextureImage();
@@ -212,8 +211,7 @@
     // completion of the method will instead be returned to the caller, so that
     // it may call releaseBufferLocked itself later.
     status_t updateAndReleaseLocked(const BufferItem& item,
-                                    PendingRelease* pendingRelease = nullptr,
-                                    const sp<Fence>& releaseFence = Fence::NO_FENCE);
+                                    PendingRelease* pendingRelease = nullptr);
 
     // Binds mTexName and the current buffer to TEXTURE_EXTERNAL target.
     // If the bind succeeds, this calls doFenceWait.
@@ -244,12 +242,6 @@
     // access the current texture buffer.
     status_t doFenceWaitLocked() const;
 
-    // syncForReleaseLocked performs the synchronization needed to release the
-    // current slot from RenderEngine.  If needed it will set the current
-    // slot's fence to guard against a producer accessing the buffer before
-    // the outstanding accesses have completed.
-    status_t syncForReleaseLocked(const sp<Fence>& releaseFence);
-
     // The default consumer usage flags that BufferLayerConsumer always sets on its
     // BufferQueue instance; these will be OR:d with any additional flags passed
     // from the BufferLayerConsumer user. In particular, BufferLayerConsumer will always
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 5833de6..b3e2a4b 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -225,8 +225,7 @@
     return mConsumer->bindTextureImage();
 }
 
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                                          const sp<Fence>& releaseFence) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
     // This boolean is used to make sure that SurfaceFlinger's shadow copy
     // of the buffer queue isn't modified when the buffer queue is returning
     // BufferItem's that weren't actually queued. This can happen in shared
@@ -262,9 +261,8 @@
     const uint64_t maxFrameNumberToAcquire =
             std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
 
-    status_t updateResult =
-            mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
-                                      maxFrameNumberToAcquire, releaseFence);
+    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
+                                                      &queuedBuffer, maxFrameNumberToAcquire);
     if (updateResult == BufferQueue::PRESENT_LATER) {
         // Producer doesn't want buffer to be displayed yet.  Signal a
         // layer update so we check again at the next opportunity.
@@ -391,7 +389,7 @@
 void BufferQueueLayer::fakeVsync() {
     mRefreshPending = false;
     bool ignored = false;
-    latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+    latchBuffer(ignored, systemTime());
     usleep(16000);
     releasePendingBuffer(systemTime());
 }
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 30107e2..fbb8c14 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -91,8 +91,7 @@
     void setFilteringEnabled(bool enabled) override;
 
     status_t bindTextureImage() override;
-    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                            const sp<Fence>& releaseFence) override;
+    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
 
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index a3d5b89..e48c41e 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -473,8 +473,7 @@
     return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence, false);
 }
 
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
-                                          const sp<Fence>& releaseFence) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
     const State& s(getDrawingState());
 
     if (!s.buffer) {
@@ -516,59 +515,7 @@
         handle->latchTime = latchTime;
     }
 
-    // Handle sync fences
-    if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
-        // TODO(alecmouri): Fail somewhere upstream if the fence is invalid.
-        if (!releaseFence->isValid()) {
-            mFlinger->mTimeStats->onDestroy(layerID);
-            return UNKNOWN_ERROR;
-        }
-
-        // Check status of fences first because merging is expensive.
-        // Merging an invalid fence with any other fence results in an
-        // invalid fence.
-        auto currentStatus = s.acquireFence->getStatus();
-        if (currentStatus == Fence::Status::Invalid) {
-            ALOGE("Existing fence has invalid state");
-            mFlinger->mTimeStats->onDestroy(layerID);
-            return BAD_VALUE;
-        }
-
-        auto incomingStatus = releaseFence->getStatus();
-        if (incomingStatus == Fence::Status::Invalid) {
-            ALOGE("New fence has invalid state");
-            mDrawingState.acquireFence = releaseFence;
-            mFlinger->mTimeStats->onDestroy(layerID);
-            return BAD_VALUE;
-        }
-
-        // If both fences are signaled or both are unsignaled, we need to merge
-        // them to get an accurate timestamp.
-        if (currentStatus == incomingStatus) {
-            char fenceName[32] = {};
-            snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
-            sp<Fence> mergedFence =
-                    Fence::merge(fenceName, mDrawingState.acquireFence, releaseFence);
-            if (!mergedFence.get()) {
-                ALOGE("failed to merge release fences");
-                // synchronization is broken, the best we can do is hope fences
-                // signal in order so the new fence will act like a union
-                mDrawingState.acquireFence = releaseFence;
-                mFlinger->mTimeStats->onDestroy(layerID);
-                return BAD_VALUE;
-            }
-            mDrawingState.acquireFence = mergedFence;
-        } else if (incomingStatus == Fence::Status::Unsignaled) {
-            // If one fence has signaled and the other hasn't, the unsignaled
-            // fence will approximately correspond with the correct timestamp.
-            // There's a small race if both fences signal at about the same time
-            // and their statuses are retrieved with unfortunate timing. However,
-            // by this point, they will have both signaled and only the timestamp
-            // will be slightly off; any dependencies after this point will
-            // already have been met.
-            mDrawingState.acquireFence = releaseFence;
-        }
-    } else {
+    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
         // Bind the new buffer to the GL texture.
         //
         // Older devices require the "implicit" synchronization provided
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index a97f0a4..0b03f49 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -125,8 +125,7 @@
     void setFilteringEnabled(bool enabled) override;
 
     status_t bindTextureImage() override;
-    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                            const sp<Fence>& releaseFence) override;
+    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
 
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8ae057f..36885db 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -534,8 +534,7 @@
      * operation, so this should be set only if needed). Typically this is used
      * to figure out if the content or size of a surface has changed.
      */
-    virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
-                             const sp<Fence>& /*releaseFence*/) {
+    virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
         return {};
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3ff7e96..e3f75e1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1661,18 +1661,6 @@
                 mHadClientComposition || getHwComposer().hasClientComposition(displayId);
     }
 
-    // Setup RenderEngine sync fences if native sync is supported.
-    if (getRenderEngine().useNativeFenceSync()) {
-        if (mHadClientComposition) {
-            base::unique_fd flushFence(getRenderEngine().flush());
-            ALOGE_IF(flushFence < 0, "Failed to flush RenderEngine!");
-            getBE().flushFence = new Fence(std::move(flushFence));
-        } else {
-            // Cleanup for hygiene.
-            getBE().flushFence = Fence::NO_FENCE;
-        }
-    }
-
     mVsyncModulator.onRefreshed(mHadClientComposition);
 
     getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo);
@@ -2982,7 +2970,7 @@
 void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
     if (layer->hasReadyFrame()) {
         bool ignored = false;
-        layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+        layer->latchBuffer(ignored, systemTime());
     }
     layer->releasePendingBuffer(systemTime());
 }
@@ -3228,7 +3216,7 @@
         Mutex::Autolock lock(mStateLock);
 
         for (auto& layer : mLayersWithQueuedFrames) {
-            if (layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence)) {
+            if (layer->latchBuffer(visibleRegions, latchTime)) {
                 mLayersPendingRefresh.push_back(layer);
             }
             layer->useSurfaceDamage();
@@ -3238,11 +3226,6 @@
         }
     }
 
-    // Clear the renderengine fence here...
-    // downstream code assumes that a cleared fence == NO_FENCE, so reassign to
-    // clear instead of sp::clear.
-    getBE().flushFence = Fence::NO_FENCE;
-
     mVisibleRegionsDirty |= visibleRegions;
 
     // If we will need to wake up at some time in the future to deal with a
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3d21a98..36302d5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -169,9 +169,6 @@
     nsecs_t mTotalTime;
     std::atomic<nsecs_t> mLastSwapTime;
 
-    // Synchronization fence from a GL composition.
-    sp<Fence> flushFence = Fence::NO_FENCE;
-
     // Double- vs. triple-buffering stats
     struct BufferingStats {
         BufferingStats()
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 3101a9b..42bdccc 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -494,7 +494,7 @@
 
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
         bool ignoredRecomputeVisibleRegions;
-        layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, Fence::NO_FENCE);
+        layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
         Mock::VerifyAndClear(test->mRenderEngine);
     }
 
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 3a8e34e..b3259de 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -33,6 +33,7 @@
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
 #include <graphicsenv/GraphicsEnv.h>
+#include <utils/Timers.h>
 #include <utils/Trace.h>
 #include <utils/Vector.h>
 
@@ -210,6 +211,8 @@
     auto ns = android_get_exported_namespace("sphal");
     if (!ns)
         return -ENOENT;
+    android::GraphicsEnv::getInstance().setDriverToLoad(
+        android::GraphicsEnv::Driver::VULKAN);
     return LoadDriver(ns, module);
 }
 
@@ -219,12 +222,16 @@
     auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
     if (!ns)
         return -ENOENT;
+    android::GraphicsEnv::getInstance().setDriverToLoad(
+        android::GraphicsEnv::Driver::VULKAN_UPDATED);
     return LoadDriver(ns, module);
 }
 
 bool Hal::Open() {
     ATRACE_CALL();
 
+    const nsecs_t openTime = systemTime();
+
     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
 
     // Use a stub device unless we successfully open a real HAL device.
@@ -250,11 +257,12 @@
         }
     }
     if (result != 0) {
+        android::GraphicsEnv::getInstance().setDriverLoaded(
+            android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
         ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
         return true;
     }
 
-    android::GraphicsEnv::getInstance().sendGpuStats();
 
     hwvulkan_device_t* device;
     ATRACE_BEGIN("hwvulkan module open");
@@ -263,6 +271,8 @@
                                      reinterpret_cast<hw_device_t**>(&device));
     ATRACE_END();
     if (result != 0) {
+        android::GraphicsEnv::getInstance().setDriverLoaded(
+            android::GraphicsEnv::Api::API_VK, false, systemTime() - openTime);
         // Any device with a Vulkan HAL should be able to open the device.
         ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
               result);
@@ -273,6 +283,9 @@
 
     hal_.InitDebugReportIndex();
 
+    android::GraphicsEnv::getInstance().setDriverLoaded(
+        android::GraphicsEnv::Api::API_VK, true, systemTime() - openTime);
+
     return true;
 }