Merge "Fix 5x and 6P crash when using HWC2to1adapter"
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 1107c99..40c6715 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -132,6 +132,7 @@
     mHwc1Device(hwc1Device),
     mHwc1MinorVersion(getMinorVersion(hwc1Device)),
     mHwc1SupportsVirtualDisplays(false),
+    mHwc1SupportsBackgroundColor(false),
     mHwc1Callbacks(std::make_unique<Callbacks>(*this)),
     mCapabilities(),
     mLayers(),
@@ -2272,7 +2273,18 @@
         bool applyAllState)
 {
     if (applyAllState || mColor.isDirty()) {
-        hwc1Layer.backgroundColor = mColor.getPendingValue();
+        // If the device does not support background color it is likely to make
+        // assumption regarding backgroundColor and handle (both fields occupy
+        // the same location in hwc_layer_1_t union).
+        // To not confuse these devices we don't set background color and we
+        // make sure handle is a null pointer.
+        if (mDisplay.getDevice().supportsBackgroundColor()) {
+            hwc1Layer.backgroundColor = mColor.getPendingValue();
+            mHasUnsupportedBackgroundColor = false;
+        } else {
+            hwc1Layer.handle = nullptr;
+            mHasUnsupportedBackgroundColor = true;
+        }
         mColor.latch();
     }
 }
@@ -2299,7 +2311,7 @@
     // supports plane alpha (depending on the version). These require us to drop
     // some or all layers to client composition.
     if (mHasUnsupportedDataspace || mHasUnsupportedPlaneAlpha ||
-            mDisplay.hasColorTransform()) {
+            mDisplay.hasColorTransform() || mHasUnsupportedBackgroundColor) {
         hwc1Layer.compositionType = HWC_FRAMEBUFFER;
         hwc1Layer.flags = HWC_SKIP_LAYER;
         return;
@@ -2369,6 +2381,18 @@
     if (mHwc1MinorVersion >= 4U) {
         mCapabilities.insert(Capability::SidebandStream);
     }
+
+    // Check for HWC background color layer support.
+    if (mHwc1MinorVersion >= 1U) {
+        int backgroundColorSupported = 0;
+        auto result = mHwc1Device->query(mHwc1Device,
+                                         HWC_BACKGROUND_LAYER_SUPPORTED,
+                                         &backgroundColorSupported);
+        if ((result == 0) && (backgroundColorSupported == 1)) {
+            ALOGV("Found support for HWC background color");
+            mHwc1SupportsBackgroundColor = true;
+        }
+    }
 }
 
 HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id)
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index 047e3aa..daa988c 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -63,6 +63,10 @@
         getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
     }
 
+    bool supportsBackgroundColor() {
+        return mHwc1SupportsBackgroundColor;
+    }
+
     // getFunction
 
     hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
@@ -576,6 +580,7 @@
             size_t mHwc1Id;
             bool mHasUnsupportedDataspace;
             bool mHasUnsupportedPlaneAlpha;
+            bool mHasUnsupportedBackgroundColor;
     };
 
     template <typename ...Args>
@@ -656,6 +661,7 @@
     struct hwc_composer_device_1* const mHwc1Device;
     const uint8_t mHwc1MinorVersion;
     bool mHwc1SupportsVirtualDisplays;
+    bool mHwc1SupportsBackgroundColor;
 
     class Callbacks;
     const std::unique_ptr<Callbacks> mHwc1Callbacks;