composer 2.4: add api to control vsync period

Add new functions to improve vsync period switching by the platform:
 - Adding a list of supported vsync periods to Config to avoid the need to expose
   separate Configs for each vsync period.
 - Adding an API to set the vsync period with timeline constraints to allow better
   synchronization with vsync period change.
 - Extending onVsync() callback to provide the current vsync period.

Test: rev up composer to 2.4 and test refresh rate switching
Bug: 141329414
Change-Id: I1a6f395d9634edadc68649d02f624f00173ec519
diff --git a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
index 6b64c16..cb391be 100644
--- a/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
+++ b/graphics/composer/2.4/utils/command-buffer/include/composer-command-buffer/2.4/ComposerCommandBuffer.h
@@ -34,7 +34,7 @@
 namespace V2_4 {
 
 using android::hardware::MessageQueue;
-using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_4::Error;
 using android::hardware::graphics::composer::V2_4::IComposerClient;
 
 // This class helps build a command queue.  Note that all sizes/lengths are in
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 c810186..ddf209b 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
@@ -20,8 +20,10 @@
 #warning "ComposerClient.h included without LOG_TAG"
 #endif
 
+#include <android/hardware/graphics/composer/2.4/IComposerCallback.h>
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 #include <composer-hal/2.4/ComposerHal.h>
+#include <composer-resources/2.1/ComposerResources.h>
 
 namespace android {
 namespace hardware {
@@ -38,6 +40,54 @@
   public:
     ComposerClientImpl(Hal* hal) : BaseType2_3(hal) {}
 
+    ~ComposerClientImpl() override { mHal->unregisterEventCallback_2_4(); }
+
+    class HalEventCallback : public Hal::EventCallback_2_4 {
+      public:
+        HalEventCallback(const sp<IComposerCallback> callback,
+                         V2_1::hal::ComposerResources* resources)
+            : mCallback(callback), mResources(resources) {}
+
+        void onHotplug(Display display, IComposerCallback::Connection connected) override {
+            if (connected == IComposerCallback::Connection::CONNECTED) {
+                mResources->addPhysicalDisplay(display);
+            } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
+                mResources->removeDisplay(display);
+            }
+
+            auto ret = mCallback->onHotplug(display, connected);
+            ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+        }
+
+        void onRefresh(Display display) override {
+            mResources->setDisplayMustValidateState(display, true);
+            auto ret = mCallback->onRefresh(display);
+            ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+        }
+
+        void onVsync(Display display, int64_t timestamp) override {
+            auto ret = mCallback->onVsync(display, timestamp);
+            ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+        }
+
+        void onVsync_2_4(Display display, int64_t timestamp,
+                         VsyncPeriodNanos vsyncPeriodNanos) override {
+            auto ret = mCallback->onVsync_2_4(display, timestamp, vsyncPeriodNanos);
+            ALOGE_IF(!ret.isOk(), "failed to send onVsync_2_4: %s", ret.description().c_str());
+        }
+
+      protected:
+        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());
+        mHal->registerEventCallback_2_4(mHalEventCallback_2_4.get());
+        return Void();
+    }
+
     Return<void> getDisplayCapabilities_2_4(
             Display display, IComposerClient::getDisplayCapabilities_2_4_cb hidl_cb) override {
         std::vector<IComposerClient::DisplayCapability> capabilities;
@@ -54,6 +104,36 @@
         return Void();
     }
 
+    Return<void> getSupportedDisplayVsyncPeriods(
+            Display display, Config config,
+            IComposerClient::getSupportedDisplayVsyncPeriods_cb hidl_cb) override {
+        std::vector<VsyncPeriodNanos> supportedVsyncPeriods;
+        Error error =
+                mHal->getSupportedDisplayVsyncPeriods(display, config, &supportedVsyncPeriods);
+        hidl_cb(error, supportedVsyncPeriods);
+        return Void();
+    }
+
+    Return<void> getDisplayVsyncPeriod(Display display,
+                                       IComposerClient::getDisplayVsyncPeriod_cb hidl_cb) override {
+        VsyncPeriodNanos vsyncPeriods;
+        Error error = mHal->getDisplayVsyncPeriod(display, &vsyncPeriods);
+        hidl_cb(error, vsyncPeriods);
+        return Void();
+    }
+
+    Return<void> setActiveConfigAndVsyncPeriod(
+            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+            const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
+            IComposerClient::setActiveConfigAndVsyncPeriod_cb hidl_cb) override {
+        int64_t newVsyncAppliedTime = 0;
+        Error error = mHal->setActiveConfigAndVsyncPeriod(display, config, vsyncPeriodNanos,
+                                                          vsyncPeriodChangeConstraints,
+                                                          &newVsyncAppliedTime);
+        hidl_cb(error, newVsyncAppliedTime);
+        return Void();
+    }
+
     static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
         auto client = std::make_unique<ComposerClientImpl>(hal);
         return client->init() ? std::move(client) : nullptr;
@@ -63,6 +143,8 @@
     using BaseType2_3 = V2_3::hal::detail::ComposerClientImpl<Interface, Hal>;
     using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
     using BaseType2_1::mHal;
+    std::unique_ptr<HalEventCallback> mHalEventCallback_2_4;
+    using BaseType2_1::mResources;
 };
 
 }  // namespace detail
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
index c3bb535..0739f62 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android/hardware/graphics/composer/2.4/types.h>
 #include <composer-hal/2.3/ComposerHal.h>
 
 namespace android {
@@ -30,16 +31,39 @@
 using common::V1_2::Dataspace;
 using common::V1_2::Hdr;
 using common::V1_2::PixelFormat;
+using V2_1::Config;
 using V2_1::Display;
-using V2_1::Error;
 using V2_1::Layer;
+using V2_4::Error;
+using V2_4::VsyncPeriodNanos;
 
 class ComposerHal : public V2_3::hal::ComposerHal {
   public:
+    class EventCallback_2_4 {
+      public:
+        virtual ~EventCallback_2_4() = default;
+        virtual void onHotplug(Display display, IComposerCallback::Connection connected) = 0;
+        virtual void onRefresh(Display display) = 0;
+        virtual void onVsync(Display display, int64_t timestamp) = 0;
+        virtual void onVsync_2_4(Display display, int64_t timestamp,
+                                 VsyncPeriodNanos vsyncPeriodNanos) = 0;
+    };
+
+    virtual void registerEventCallback_2_4(EventCallback_2_4* callback) = 0;
+
+    virtual void unregisterEventCallback_2_4() = 0;
+
     virtual Error getDisplayCapabilities_2_4(
             Display display, std::vector<IComposerClient::DisplayCapability>* outCapabilities) = 0;
     virtual Error getDisplayConnectionType(Display display,
                                            IComposerClient::DisplayConnectionType* outType) = 0;
+    virtual Error getSupportedDisplayVsyncPeriods(
+            Display display, Config config, std::vector<VsyncPeriodNanos>* outVsyncPeriod) = 0;
+    virtual Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) = 0;
+    virtual Error setActiveConfigAndVsyncPeriod(
+            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+            const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
+            int64_t* outNewVsyncAppliedTime) = 0;
 };
 
 }  // namespace hal
diff --git a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
index fd05f66..3420c8c 100644
--- a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
+++ b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
@@ -22,6 +22,7 @@
 
 #include <type_traits>
 
+#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 #include <composer-hal/2.4/ComposerHal.h>
 #include <composer-passthrough/2.3/HwcHal.h>
 
@@ -39,18 +40,49 @@
 using common::V1_2::Dataspace;
 using common::V1_2::Hdr;
 using common::V1_2::PixelFormat;
+using V2_1::Config;
 using V2_1::Display;
-using V2_1::Error;
+using V2_4::Error;
 
 // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
 template <typename Hal>
 class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
   public:
+    void registerEventCallback_2_4(hal::ComposerHal::EventCallback_2_4* callback) override {
+        mEventCallback_2_4 = callback;
+
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(vsync_2_4_Hook));
+    }
+
+    void unregisterEventCallback_2_4() override {
+        // we assume the callback functions
+        //
+        //  - can be unregistered
+        //  - can be in-flight
+        //  - will never be called afterward
+        //
+        // which is likely incorrect
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this, nullptr);
+
+        mEventCallback_2_4 = nullptr;
+    }
+
     Error getDisplayCapabilities_2_4(
             Display display,
             std::vector<IComposerClient::DisplayCapability>* outCapabilities) override {
         std::vector<V2_3::IComposerClient::DisplayCapability> capabilities;
-        Error error = BaseType2_3::getDisplayCapabilities(display, &capabilities);
+        V2_3::Error error_2_3 = BaseType2_3::getDisplayCapabilities(display, &capabilities);
+        Error error = static_cast<Error>(error_2_3);
         if (error != Error::NONE) {
             return error;
         }
@@ -74,6 +106,63 @@
         return static_cast<Error>(error);
     }
 
+    Error getSupportedDisplayVsyncPeriods(Display display, Config config,
+                                          std::vector<VsyncPeriodNanos>* outVsyncPeriods) override {
+        if (!mDispatch.getSupportedDisplayVsyncPeriods) {
+            return Error::UNSUPPORTED;
+        }
+
+        uint32_t count = 0;
+        int32_t error = mDispatch.getSupportedDisplayVsyncPeriods(mDevice, display, config, &count,
+                                                                  nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        outVsyncPeriods->resize(count);
+        error = mDispatch.getSupportedDisplayVsyncPeriods(mDevice, display, config, &count,
+                                                          outVsyncPeriods->data());
+        if (error != HWC2_ERROR_NONE) {
+            *outVsyncPeriods = std::vector<VsyncPeriodNanos>();
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
+    Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) override {
+        if (!mDispatch.getDisplayVsyncPeriod) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error = mDispatch.getDisplayVsyncPeriod(mDevice, display, outVsyncPeriod);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
+    Error setActiveConfigAndVsyncPeriod(
+            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+            const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
+            int64_t* outNewVsyncAppliedTime) override {
+        if (!mDispatch.setActiveConfigAndVsyncPeriod) {
+            return Error::UNSUPPORTED;
+        }
+
+        hwc_vsync_period_change_constraints_t vsync_period_change_constraints;
+        vsync_period_change_constraints.desiredTimeNanos =
+                vsyncPeriodChangeConstraints.desiredTimeNanos;
+        vsync_period_change_constraints.seamlessRequired =
+                vsyncPeriodChangeConstraints.seamlessRequired;
+
+        int32_t error = mDispatch.setActiveConfigAndVsyncPeriod(
+                mDevice, display, config, vsyncPeriodNanos, &vsync_period_change_constraints,
+                outNewVsyncAppliedTime);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
   protected:
     bool initDispatch() override {
         if (!BaseType2_3::initDispatch()) {
@@ -82,14 +171,51 @@
 
         this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE,
                                    &mDispatch.getDisplayConnectionType);
+        this->initOptionalDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback);
+        this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_DISPLAY_VSYNC_PERIODS,
+                                   &mDispatch.getSupportedDisplayVsyncPeriods);
+        this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
+                                   &mDispatch.getDisplayVsyncPeriod);
+        this->initOptionalDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_AND_VSYNC_PERIOD,
+                                   &mDispatch.setActiveConfigAndVsyncPeriod);
         return true;
     }
 
+    static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                            int32_t connected) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback_2_4->onHotplug(display,
+                                           static_cast<IComposerCallback::Connection>(connected));
+    }
+
+    static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback_2_4->onRefresh(display);
+    }
+
+    static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                          int64_t timestamp) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback_2_4->onVsync(display, timestamp);
+    }
+
+    static void vsync_2_4_Hook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                               int64_t timestamp, hwc2_vsync_period_t vsyncPeriodNanos) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback_2_4->onVsync_2_4(display, timestamp, vsyncPeriodNanos);
+    }
+
   private:
     struct {
         HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType;
+        HWC2_PFN_REGISTER_CALLBACK registerCallback;
+        HWC2_PFN_GET_SUPPORTED_DISPLAY_VSYNC_PERIODS getSupportedDisplayVsyncPeriods;
+        HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod;
+        HWC2_PFN_SET_ACTIVE_CONFIG_AND_VSYNC_PERIOD setActiveConfigAndVsyncPeriod;
     } mDispatch = {};
 
+    hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr;
+
     using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
     using BaseType2_3 = V2_3::passthrough::detail::HwcHalImpl<Hal>;
     using BaseType2_1::mDevice;
diff --git a/graphics/composer/2.4/utils/vts/ComposerVts.cpp b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
index 937b50e..b02a59a 100644
--- a/graphics/composer/2.4/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
@@ -25,7 +25,7 @@
 namespace V2_4 {
 namespace vts {
 
-using V2_1::Error;
+using V2_4::Error;
 
 Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>()) {}
 
@@ -70,6 +70,40 @@
     return error;
 }
 
+Error ComposerClient::getSupportedDisplayVsyncPeriods(
+        Display display, Config config, std::vector<VsyncPeriodNanos>* outSupportedVsyncPeriods) {
+    Error error = Error::NONE;
+    mClient->getSupportedDisplayVsyncPeriods(
+            display, config, [&](const auto& tmpError, const auto& tmpSupportedVsyncPeriods) {
+                error = tmpError;
+                *outSupportedVsyncPeriods = tmpSupportedVsyncPeriods;
+            });
+    return error;
+}
+
+Error ComposerClient::getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) {
+    Error error = Error::NONE;
+    mClient->getDisplayVsyncPeriod(display, [&](const auto& tmpError, const auto& tmpVsyncPeriod) {
+        error = tmpError;
+        *outVsyncPeriod = tmpVsyncPeriod;
+    });
+    return error;
+}
+
+Error ComposerClient::setActiveConfigAndVsyncPeriod(
+        Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+        const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
+        int64_t* outNewVsyncAppliedTime) {
+    Error error = Error::NONE;
+    mClient->setActiveConfigAndVsyncPeriod(
+            display, config, vsyncPeriodNanos, vsyncPeriodChangeConstraints,
+            [&](const auto& tmpError, const auto& tmpNewVsyncAppliedTime) {
+                error = tmpError;
+                *outNewVsyncAppliedTime = tmpNewVsyncAppliedTime;
+            });
+    return error;
+}
+
 }  // namespace vts
 }  // namespace V2_4
 }  // namespace composer
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
index a7d7f86..e8a3905 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
@@ -37,10 +37,12 @@
 using common::V1_2::Dataspace;
 using common::V1_2::Hdr;
 using common::V1_2::PixelFormat;
+using V2_1::Config;
 using V2_1::Display;
-using V2_1::Error;
+using V2_4::Error;
 using V2_4::IComposer;
 using V2_4::IComposerClient;
+using V2_4::VsyncPeriodNanos;
 
 class ComposerClient;
 
@@ -74,6 +76,16 @@
     Error getDisplayConnectionType(Display display,
                                    IComposerClient::DisplayConnectionType* outType);
 
+    Error getSupportedDisplayVsyncPeriods(Display display, Config config,
+                                          std::vector<VsyncPeriodNanos>* outSupportedVsyncPeriods);
+
+    Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriods);
+
+    Error setActiveConfigAndVsyncPeriod(
+            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+            const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
+            int64_t* outNewVsyncAppliedTime);
+
   private:
     const sp<IComposerClient> mClient;
 };