Merge "ComposerClient 2.4: Clean cache on hotplug" into sc-dev
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
index 3d74af4..46f5d6e 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -98,7 +98,7 @@
                      // display change and thus the framework may want to reallocate buffers. We
                      // need to free all cached handles, since they are holding a strong reference
                      // to the underlying buffers.
-                     cleanDisplayResources(display);
+                     cleanDisplayResources(display, mResources, mHal);
                      mResources->removeDisplay(display);
                  }
                  mResources->addPhysicalDisplay(display);
@@ -125,56 +125,6 @@
          Hal* const mHal;
          const sp<IComposerCallback> mCallback;
          ComposerResources* const mResources;
-
-         void cleanDisplayResources(Display display) {
-             size_t cacheSize;
-             Error err = mResources->getDisplayClientTargetCacheSize(display, &cacheSize);
-             if (err == Error::NONE) {
-                 for (int slot = 0; slot < cacheSize; slot++) {
-                     ComposerResources::ReplacedHandle replacedBuffer(/*isBuffer*/ true);
-                     // Replace the buffer slots with NULLs. Keep the old handle until it is
-                     // replaced in ComposerHal, otherwise we risk leaving a dangling pointer.
-                     const native_handle_t* clientTarget = nullptr;
-                     err = mResources->getDisplayClientTarget(display, slot, /*useCache*/ true,
-                                                              /*rawHandle*/ nullptr, &clientTarget,
-                                                              &replacedBuffer);
-                     if (err != Error::NONE) {
-                         continue;
-                     }
-                     const std::vector<hwc_rect_t> damage;
-                     err = mHal->setClientTarget(display, clientTarget, /*fence*/ -1, 0, damage);
-                     ALOGE_IF(err != Error::NONE,
-                              "Can't clean slot %d of the client target buffer"
-                              "cache for display %" PRIu64,
-                              slot, display);
-                 }
-             } else {
-                 ALOGE("Can't clean client target cache for display %" PRIu64, display);
-             }
-
-             err = mResources->getDisplayOutputBufferCacheSize(display, &cacheSize);
-             if (err == Error::NONE) {
-                 for (int slot = 0; slot < cacheSize; slot++) {
-                     // Replace the buffer slots with NULLs. Keep the old handle until it is
-                     // replaced in ComposerHal, otherwise we risk leaving a dangling pointer.
-                     ComposerResources::ReplacedHandle replacedBuffer(/*isBuffer*/ true);
-                     const native_handle_t* outputBuffer = nullptr;
-                     err = mResources->getDisplayOutputBuffer(display, slot, /*useCache*/ true,
-                                                              /*rawHandle*/ nullptr, &outputBuffer,
-                                                              &replacedBuffer);
-                     if (err != Error::NONE) {
-                         continue;
-                     }
-                     err = mHal->setOutputBuffer(display, outputBuffer, /*fence*/ -1);
-                     ALOGE_IF(err != Error::NONE,
-                              "Can't clean slot %d of the output buffer cache"
-                              "for display %" PRIu64,
-                              slot, display);
-                 }
-             } else {
-                 ALOGE("Can't clean output buffer cache for display %" PRIu64, display);
-             }
-         }
     };
 
     Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
@@ -380,6 +330,57 @@
         return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
     }
 
+    static void cleanDisplayResources(Display display, ComposerResources* const resources,
+                                      Hal* const hal) {
+        size_t cacheSize;
+        Error err = resources->getDisplayClientTargetCacheSize(display, &cacheSize);
+        if (err == Error::NONE) {
+            for (int slot = 0; slot < cacheSize; slot++) {
+                ComposerResources::ReplacedHandle replacedBuffer(/*isBuffer*/ true);
+                // Replace the buffer slots with NULLs. Keep the old handle until it is
+                // replaced in ComposerHal, otherwise we risk leaving a dangling pointer.
+                const native_handle_t* clientTarget = nullptr;
+                err = resources->getDisplayClientTarget(display, slot, /*useCache*/ true,
+                                                        /*rawHandle*/ nullptr, &clientTarget,
+                                                        &replacedBuffer);
+                if (err != Error::NONE) {
+                    continue;
+                }
+                const std::vector<hwc_rect_t> damage;
+                err = hal->setClientTarget(display, clientTarget, /*fence*/ -1, 0, damage);
+                ALOGE_IF(err != Error::NONE,
+                         "Can't clean slot %d of the client target buffer"
+                         "cache for display %" PRIu64,
+                         slot, display);
+            }
+        } else {
+            ALOGE("Can't clean client target cache for display %" PRIu64, display);
+        }
+
+        err = resources->getDisplayOutputBufferCacheSize(display, &cacheSize);
+        if (err == Error::NONE) {
+            for (int slot = 0; slot < cacheSize; slot++) {
+                // Replace the buffer slots with NULLs. Keep the old handle until it is
+                // replaced in ComposerHal, otherwise we risk leaving a dangling pointer.
+                ComposerResources::ReplacedHandle replacedBuffer(/*isBuffer*/ true);
+                const native_handle_t* outputBuffer = nullptr;
+                err = resources->getDisplayOutputBuffer(display, slot, /*useCache*/ true,
+                                                        /*rawHandle*/ nullptr, &outputBuffer,
+                                                        &replacedBuffer);
+                if (err != Error::NONE) {
+                    continue;
+                }
+                err = hal->setOutputBuffer(display, outputBuffer, /*fence*/ -1);
+                ALOGE_IF(err != Error::NONE,
+                         "Can't clean slot %d of the output buffer cache"
+                         "for display %" PRIu64,
+                         slot, display);
+            }
+        } else {
+            ALOGE("Can't clean output buffer cache for display %" PRIu64, display);
+        }
+    }
+
     void destroyResources() {
         // We want to call hwc2_close here (and move hwc2_open to the
         // constructor), with the assumption that hwc2_close would
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
index c889069..3464342 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
@@ -45,12 +45,21 @@
 
     class HalEventCallback : public Hal::EventCallback_2_4 {
       public:
-        HalEventCallback(const sp<IComposerCallback> callback,
+        HalEventCallback(Hal* hal, const sp<IComposerCallback> callback,
                          V2_1::hal::ComposerResources* resources)
-            : mCallback(callback), mResources(resources) {}
+            : mHal(hal), mCallback(callback), mResources(resources) {}
 
         void onHotplug(Display display, IComposerCallback::Connection connected) override {
             if (connected == IComposerCallback::Connection::CONNECTED) {
+                if (mResources->hasDisplay(display)) {
+                    // This is a subsequent hotplug "connected" for a display. This signals a
+                    // display change and thus the framework may want to reallocate buffers. We
+                    // need to free all cached handles, since they are holding a strong reference
+                    // to the underlying buffers.
+                    V2_1::hal::detail::ComposerClientImpl<Interface, Hal>::cleanDisplayResources(
+                            display, mResources, mHal);
+                    mResources->removeDisplay(display);
+                }
                 mResources->addPhysicalDisplay(display);
             } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
                 mResources->removeDisplay(display);
@@ -91,13 +100,15 @@
         }
 
       protected:
+        Hal* const mHal;
         const sp<IComposerCallback> mCallback;
         V2_1::hal::ComposerResources* const mResources;
     };
 
     Return<void> registerCallback_2_4(const sp<IComposerCallback>& callback) override {
         // no locking as we require this function to be called only once
-        mHalEventCallback_2_4 = std::make_unique<HalEventCallback>(callback, mResources.get());
+        mHalEventCallback_2_4 =
+                std::make_unique<HalEventCallback>(mHal, callback, mResources.get());
         mHal->registerEventCallback_2_4(mHalEventCallback_2_4.get());
         return Void();
     }