Merge "Mark layers with color transform client composition if not implemented."
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
index 436e461..5826b12 100644
--- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -162,6 +162,7 @@
 
     Error destroyLayer(Display display, Layer layer) override {
         int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
+        onLayerDestroyed(display, layer);
         return static_cast<Error>(err);
     }
 
@@ -327,6 +328,7 @@
                           std::vector<IComposerClient::Composition>* outCompositionTypes,
                           uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
                           std::vector<uint32_t>* outRequestMasks) override {
+        onBeforeValidateDisplay(display);
         uint32_t typesCount = 0;
         uint32_t reqsCount = 0;
         int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
@@ -335,17 +337,15 @@
             return static_cast<Error>(err);
         }
 
-        err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr);
+        err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr);
         if (err != HWC2_ERROR_NONE) {
             return static_cast<Error>(err);
         }
 
         std::vector<Layer> changedLayers(typesCount);
         std::vector<IComposerClient::Composition> compositionTypes(typesCount);
-        err = mDispatch.getChangedCompositionTypes(
-            mDevice, display, &typesCount, changedLayers.data(),
-            reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
-                compositionTypes.data()));
+        err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(),
+                                         compositionTypes.data());
         if (err != HWC2_ERROR_NONE) {
             return static_cast<Error>(err);
         }
@@ -578,6 +578,15 @@
         return true;
     }
 
+    virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount,
+                                               Layer* outChangedLayers,
+                                               IComposerClient::Composition* outCompositionTypes) {
+        return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers,
+                                                  outCompositionTypes);
+    }
+    virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {}
+    virtual void onBeforeValidateDisplay(Display /* display */) {}
+
     static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
                             int32_t connected) {
         auto hal = static_cast<HwcHalImpl*>(callbackData);
@@ -596,6 +605,15 @@
         hal->mEventCallback->onVsync(display, timestamp);
     }
 
+    int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount,
+                                               Layer* outChangedLayers,
+                                               IComposerClient::Composition* outCompositionTypes) {
+        return mDispatch.getChangedCompositionTypes(
+                mDevice, display, outTypesCount, outChangedLayers,
+                reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+                        outCompositionTypes));
+    }
+
     hwc2_device_t* mDevice = nullptr;
 
     std::unordered_set<hwc2_capability_t> mCapabilities;
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index 070cf80..9d67e04 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -42,6 +42,20 @@
 using V2_1::Display;
 using V2_1::Error;
 
+namespace {
+
+bool isIdentityMatrix(const float* matrix) {
+    if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 &&
+        matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 &&
+        matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 &&
+        matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) {
+        return true;
+    }
+    return false;
+}
+
+}  // namespace
+
 // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
 template <typename Hal>
 class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
@@ -130,6 +144,16 @@
 
     Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override {
         if (!mDispatch.setLayerColorTransform) {
+            if (isIdentityMatrix(matrix)) {
+                // If an identity matrix is set, then we can remove the layer from client
+                // composition list.
+                mClientCompositionLayers[display].erase(layer);
+                return Error::UNSUPPORTED;
+            }
+            // if setLayerColorTransform is not implemented, per spec we want to make sure the
+            // layer marked as client composition, and thus we maintain a list, and mark all these
+            // layers as client composition later before validate the display.
+            mClientCompositionLayers[display].insert(layer);
             return Error::UNSUPPORTED;
         }
         int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix);
@@ -294,7 +318,79 @@
         return true;
     }
 
-   private:
+    int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount,
+                                       Layer* outChangedLayers,
+                                       IComposerClient::Composition* outCompositionTypes) override {
+        if (outChangedLayers == nullptr && outCompositionTypes == nullptr) {
+            uint32_t typesCount = 0;
+            int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount,
+                                                                            nullptr, nullptr);
+            if (error != HWC2_ERROR_NONE) {
+                return error;
+            }
+            mChangedLayersCache[display].reserve(typesCount);
+            mCompositionTypesCache[display].reserve(typesCount);
+            error = BaseType2_1::getChangedCompositionTypesInternal(
+                    display, &typesCount, mChangedLayersCache[display].data(),
+                    mCompositionTypesCache[display].data());
+            if (error != HWC2_ERROR_NONE) {
+                return error;
+            }
+            for (Layer layer : mClientCompositionLayers[display]) {
+                bool exist = false;
+                for (uint32_t i = 0; i < typesCount; ++i) {
+                    if (mChangedLayersCache[display][i] == layer) {
+                        exist = true;
+                        break;
+                    }
+                }
+                if (!exist) {
+                    mChangedLayersCache[display].push_back(layer);
+                    mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT);
+                }
+            }
+            *outTypesCount = mChangedLayersCache[display].size();
+            return error;
+        }
+        for (uint32_t i = 0; i < *outTypesCount; ++i) {
+            if (outChangedLayers != nullptr) {
+                outChangedLayers[i] = mChangedLayersCache[display][i];
+            }
+            if (outCompositionTypes != nullptr) {
+                outCompositionTypes[i] = mCompositionTypesCache[display][i];
+            }
+        }
+        return HWC2_ERROR_NONE;
+    }
+
+    void onLayerDestroyed(Display display, Layer layer) override {
+        if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) {
+            return;
+        }
+        mClientCompositionLayers[display].erase(layer);
+    }
+
+    void onBeforeValidateDisplay(Display display) override {
+        if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) {
+            return;
+        }
+
+        // clear the cache proactively so that we don't hold too much memory over time.
+        mChangedLayersCache[display].clear();
+        mCompositionTypesCache[display].clear();
+
+        // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to
+        // follow the spec to make sure those layers marked as client composition before validate
+        // the display.
+        if (!mDispatch.setLayerColorTransform) {
+            for (Layer layer : mClientCompositionLayers[display]) {
+                BaseType2_1::setLayerCompositionType(
+                        display, layer, static_cast<int32_t>(IComposerClient::Composition::CLIENT));
+            }
+        }
+    }
+
+  private:
     struct {
         HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
         HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform;
@@ -318,6 +414,9 @@
     using BaseType2_2::getRenderIntents;
     using BaseType2_2::setColorMode_2_2;
     using BaseType2_2::setLayerPerFrameMetadata;
+    std::map<Display, std::set<Layer>> mClientCompositionLayers;
+    std::map<Display, std::vector<Layer>> mChangedLayersCache;
+    std::map<Display, std::vector<IComposerClient::Composition>> mCompositionTypesCache;
 };
 
 }  // namespace detail