Query the new DisplayCapability for DISPLAY_DECORATION

This allows clients (i.e. SystemUi) to know whether to use
Composition.DISPLAY_DECORATION.

Bug: 193170859
Test: manual
Test: TODO (b/212697197)

Change-Id: I0d3e93bb04937f81e95ef77d196b861621bbdc8d
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 7f73013..a931709 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1134,6 +1134,34 @@
         return NO_ERROR;
     }
 
+    status_t getDisplayDecorationSupport(const sp<IBinder>& displayToken,
+                                         bool* outSupport) const override {
+        Parcel data, reply;
+        status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (error != NO_ERROR) {
+            ALOGE("getDisplayDecorationSupport: failed to write interface token: %d", error);
+            return error;
+        }
+        error = data.writeStrongBinder(displayToken);
+        if (error != NO_ERROR) {
+            ALOGE("getDisplayDecorationSupport: failed to write display token: %d", error);
+            return error;
+        }
+        error = remote()->transact(BnSurfaceComposer::GET_DISPLAY_DECORATION_SUPPORT, data, &reply);
+        if (error != NO_ERROR) {
+            ALOGE("getDisplayDecorationSupport: failed to transact: %d", error);
+            return error;
+        }
+        bool support;
+        error = reply.readBool(&support);
+        if (error != NO_ERROR) {
+            ALOGE("getDisplayDecorationSupport: failed to read support: %d", error);
+            return error;
+        }
+        *outSupport = support;
+        return NO_ERROR;
+    }
+
     status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
                           int8_t compatibility, int8_t changeFrameRateStrategy) override {
         Parcel data, reply;
@@ -2016,6 +2044,19 @@
             return setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ,
                                            lightRadius);
         }
+        case GET_DISPLAY_DECORATION_SUPPORT: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> displayToken;
+            status_t error = data.readNullableStrongBinder(&displayToken);
+            if (error != NO_ERROR) {
+                ALOGE("getDisplayDecorationSupport: failed to read display token: %d", error);
+                return error;
+            }
+            bool support = false;
+            error = getDisplayDecorationSupport(displayToken, &support);
+            reply->writeBool(support);
+            return error;
+        }
         case SET_FRAME_RATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> binder;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index cf04ec8..6653636 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2218,6 +2218,12 @@
                                                                           lightRadius);
 }
 
+bool SurfaceComposerClient::getDisplayDecorationSupport(const sp<IBinder>& displayToken) {
+    bool support = false;
+    ComposerService::getComposerService()->getDisplayDecorationSupport(displayToken, &support);
+    return support;
+}
+
 int SurfaceComposerClient::getGPUContextPriority() {
     return ComposerService::getComposerService()->getGPUContextPriority();
 }
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 2546e4c..69dce9d 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -508,6 +508,22 @@
                                              float lightRadius) = 0;
 
     /*
+     * Gets whether a display supports DISPLAY_DECORATION layers.
+     *
+     * displayToken
+     *      The token of the display.
+     * outSupport
+     *      An output parameter for whether the display supports
+     *      DISPLAY_DECORATION layers.
+     *
+     * Returns NO_ERROR upon success. Otherwise,
+     *      NAME_NOT_FOUND if the display is invalid, or
+     *      BAD_VALUE      if the output parameter is invalid.
+     */
+    virtual status_t getDisplayDecorationSupport(const sp<IBinder>& displayToken,
+                                                 bool* outSupport) const = 0;
+
+    /*
      * Sets the intended frame rate for a surface. See ANativeWindow_setFrameRate() for more info.
      */
     virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
@@ -628,6 +644,7 @@
         ADD_WINDOW_INFOS_LISTENER,
         REMOVE_WINDOW_INFOS_LISTENER,
         GET_PRIMARY_PHYSICAL_DISPLAY_ID,
+        GET_DISPLAY_DECORATION_SUPPORT,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 17b4846..87606d6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -272,6 +272,16 @@
     static status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
                                             float lightPosY, float lightPosZ, float lightRadius);
 
+    /*
+     * Returns whether a display supports DISPLAY_DECORATION layers.
+     *
+     * displayToken
+     *      The token of the display.
+     *
+     * Returns whether a display supports DISPLAY_DECORATION layers.
+     */
+    static bool getDisplayDecorationSupport(const sp<IBinder>& displayToken);
+
     // ------------------------------------------------------------------------
     // surface creation / destruction
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d6ac3f9..d5e089a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -882,6 +882,11 @@
         return NO_ERROR;
     }
 
+    status_t getDisplayDecorationSupport(const sp<IBinder>& /*displayToken*/,
+                                         bool* /*outSupport*/) const override {
+        return NO_ERROR;
+    }
+
     status_t setFrameRate(const sp<IGraphicBufferProducer>& /*surface*/, float /*frameRate*/,
                           int8_t /*compatibility*/, int8_t /*changeFrameRateStrategy*/) override {
         return NO_ERROR;
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index e33dc0f..ee06e03 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -136,6 +136,8 @@
             return "AutoLowLatencyMode";
         case aidl::android::hardware::graphics::composer3::DisplayCapability::SUSPEND:
             return "Suspend";
+        case aidl::android::hardware::graphics::composer3::DisplayCapability::DISPLAY_DECORATION:
+            return "DisplayDecoration";
         default:
             return "Unknown";
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 89f3bd6..d690ede 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1748,6 +1748,23 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getDisplayDecorationSupport(const sp<IBinder>& displayToken,
+                                                     bool* outSupport) const {
+    if (!displayToken || !outSupport) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mStateLock);
+
+    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
+    if (!displayId) {
+        return NAME_NOT_FOUND;
+    }
+    *outSupport =
+            getHwComposer().hasDisplayCapability(*displayId, DisplayCapability::DISPLAY_DECORATION);
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
@@ -5339,6 +5356,7 @@
         // special permissions.
         case SET_FRAME_RATE:
         case GET_DISPLAY_BRIGHTNESS_SUPPORT:
+        case GET_DISPLAY_DECORATION_SUPPORT:
         // captureLayers and captureDisplay will handle the permission check in the function
         case CAPTURE_LAYERS:
         case CAPTURE_DISPLAY:
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e1b52c5..2d1f9ba 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -594,6 +594,8 @@
     status_t notifyPowerBoost(int32_t boostId) override;
     status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
                                      float lightPosY, float lightPosZ, float lightRadius) override;
+    status_t getDisplayDecorationSupport(const sp<IBinder>& displayToken,
+                                         bool* outSupport) const override;
     status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
                           int8_t compatibility, int8_t changeFrameRateStrategy) override;