Merge "[Graphics] Introduce per display capability."
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
index 7856658..87002ec 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -27,6 +27,42 @@
 
 interface IComposerClient extends @2.2::IComposerClient {
 
+    // TODO: Move this enum to LLNDK after we decide where to put graphic types.
+    /**
+     * Required capabilities which are supported by the display. The
+     * particular set of supported capabilities for a given display may be
+     * retrieved using getDisplayCapabilities.
+     */
+    enum DisplayCapability : uint32_t {
+        INVALID = 0,
+
+        /**
+         * Specifies that the display must a color transform even when
+         * either the client or the device has chosen that all layers should
+         * be composed by the client. This prevents the client from applying
+         * the color transform during its composition step.
+         * If getDisplayCapabilities is supported, the global capability
+         * SKIP_CLIENT_COLOR_TRANSFORM is ignored.
+         * If getDisplayCapabilities is not supported, and the global capability
+         * SKIP_CLIENT_COLOR_TRANSFORM is returned by getCapabilities,
+         * then all displays must be treated as having
+         * SKIP_CLIENT_COLOR_TRANSFORM.
+         */
+        SKIP_CLIENT_COLOR_TRANSFORM = 1,
+
+        /**
+         * Specifies that the display supports PowerMode::DOZE and
+         * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit
+         * over DOZE (see the definition of PowerMode for more information),
+         * but if both DOZE and DOZE_SUSPEND are no different from
+         * PowerMode::ON, the device must not claim support.
+         * Must be returned by getDisplayCapabilities when getDozeSupport
+         * indicates the display supports PowerMode::DOZE and
+         * PowerMode::DOZE_SUSPEND.
+         */
+        DOZE = 2,
+    };
+
     enum Command : @2.2::IComposerClient.Command {
         /**
          * SET_LAYER_COLOR_TRANSFORM has this pseudo prototype
@@ -350,4 +386,17 @@
      */
     setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent)
           generates (Error error);
+
+    /**
+     * Provides a list of supported capabilities (as described in the
+     * definition of DisplayCapability above). This list must not change after
+     * initialization.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     * @return capabilities is a list of supported capabilities.
+     */
+    getDisplayCapabilities(Display display)
+              generates (Error error,
+                         vec<DisplayCapability> capabilities);
 };
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
index be0ef4c..69872d2 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -73,6 +73,14 @@
         return err;
     }
 
+    Return<void> getDisplayCapabilities(
+        Display display, IComposerClient::getDisplayCapabilities_cb hidl_cb) override {
+        hidl_vec<IComposerClient::DisplayCapability> capabilities;
+        Error error = mHal->getDisplayCapabilities(display, &capabilities);
+        hidl_cb(error, capabilities);
+        return Void();
+    }
+
     static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
         auto client = std::make_unique<ComposerClientImpl>(hal);
         return client->init() ? std::move(client) : nullptr;
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
index 8ca5d75..c7de848 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -84,6 +84,8 @@
                                             hidl_vec<uint64_t>& sampleComponent1,
                                             hidl_vec<uint64_t>& sampleComponent2,
                                             hidl_vec<uint64_t>& sampleComponent3) = 0;
+    virtual Error getDisplayCapabilities(
+        Display display, hidl_vec<IComposerClient::DisplayCapability>* outCapabilities) = 0;
 };
 
 }  // namespace hal
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 8d444c8..f7ce7e8 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
@@ -163,6 +163,29 @@
         return static_cast<Error>(errorRaw);
     }
 
+    Error getDisplayCapabilities(
+        Display display, hidl_vec<IComposerClient::DisplayCapability>* outCapabilities) override {
+        if (!mDispatch.getDisplayCapabilities) {
+            return Error::UNSUPPORTED;
+        }
+
+        uint32_t count = 0;
+        int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        outCapabilities->resize(count);
+        error = mDispatch.getDisplayCapabilities(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<IComposerClient::DisplayCapability>::type*>(
+                outCapabilities->data()));
+        if (error != HWC2_ERROR_NONE) {
+            *outCapabilities = hidl_vec<IComposerClient::DisplayCapability>();
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
    protected:
     bool initDispatch() override {
         if (!BaseType2_2::initDispatch()) {
@@ -179,6 +202,8 @@
                                    &mDispatch.setDisplayedContentSamplingEnabled);
         this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLE,
                                    &mDispatch.getDisplayedContentSample);
+        this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES,
+                                   &mDispatch.getDisplayCapabilities);
         return true;
     }
 
@@ -189,6 +214,7 @@
         HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES getDisplayedContentSamplingAttributes;
         HWC2_PFN_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED setDisplayedContentSamplingEnabled;
         HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE getDisplayedContentSample;
+        HWC2_PFN_GET_DISPLAY_CAPABILITIES getDisplayCapabilities;
     } mDispatch = {};
 
     using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
index 9304992..c631c50 100644
--- a/graphics/composer/2.3/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
@@ -150,6 +150,15 @@
     return error;
 }
 
+std::vector<IComposerClient::DisplayCapability> ComposerClient::getDisplayCapabilities(
+    Display display) {
+    std::vector<IComposerClient::DisplayCapability> capabilities;
+    mClient->getDisplayCapabilities(
+        display, [&](const auto&, const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
+
+    return capabilities;
+}
+
 }  // namespace vts
 }  // namespace V2_3
 }  // namespace composer
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
index 4b9c955..d3aa779 100644
--- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -91,6 +91,7 @@
 
     bool getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
                                     PixelFormat format, Dataspace dataspace);
+    std::vector<IComposerClient::DisplayCapability> getDisplayCapabilities(Display display);
 
    private:
     const sp<IComposerClient> mClient;
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index a294825..6c5cb5d 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -427,6 +427,23 @@
     }
 }
 
+/*
+ * getDisplayCapabilities is required in composer 2.3
+ * Test some constraints.
+ */
+TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBasic) {
+    auto capabilities = mComposerClient->getDisplayCapabilities(mPrimaryDisplay);
+    bool hasDozeSupport = std::find(capabilities.begin(), capabilities.end(),
+                                    IComposerClient::DisplayCapability::DOZE) != capabilities.end();
+    EXPECT_EQ(mComposerClient->getDozeSupport(mPrimaryDisplay), hasDozeSupport);
+}
+
+TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
+    mComposerClient->getRaw()->getDisplayCapabilities(
+        mInvalidDisplayId,
+        [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_DISPLAY, tmpError); });
+}
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_3