OSDN Git Service

SurfaceFlinger: add DISPLAY_EVENT_CONFIG_CHANGED
authorAdy Abraham <adyabr@google.com>
Thu, 14 Feb 2019 00:07:27 +0000 (16:07 -0800)
committerAdy Abraham <adyabr@google.com>
Mon, 25 Feb 2019 21:18:50 +0000 (13:18 -0800)
Add a new event to DisplayEventReceiver for display
configuration change. This event is sent by SF when display config
is changed.

Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Bug: 122905403
Change-Id: Ibb7e0ce7b83b91259ccb0e9c982f5e378b0ebfaf

libs/gui/include/gui/DisplayEventReceiver.h
services/surfaceflinger/Scheduler/EventThread.cpp
services/surfaceflinger/Scheduler/EventThread.h
services/surfaceflinger/Scheduler/Scheduler.cpp
services/surfaceflinger/Scheduler/Scheduler.h
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h
services/surfaceflinger/tests/unittests/EventThreadTest.cpp
services/surfaceflinger/tests/unittests/mock/MockEventThread.h

index 8c3f463..22de751 100644 (file)
@@ -52,6 +52,7 @@ public:
     enum {
         DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
         DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
+        DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),
     };
 
     struct Event {
@@ -70,10 +71,15 @@ public:
             bool connected;
         };
 
+        struct Config {
+            int32_t configId;
+        };
+
         Header header;
         union {
             VSync vsync;
             Hotplug hotplug;
+            Config config;
         };
     };
 
index 4b500f1..78bf7c5 100644 (file)
@@ -97,6 +97,13 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times
     return event;
 }
 
+DisplayEventReceiver::Event makeConfigChanged(uint32_t displayId, int32_t configId) {
+    DisplayEventReceiver::Event event;
+    event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()};
+    event.config.configId = configId;
+    return event;
+}
+
 } // namespace
 
 EventThreadConnection::EventThreadConnection(EventThread* eventThread,
@@ -307,6 +314,13 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected)
     mCondition.notify_all();
 }
 
+void EventThread::onConfigChanged(PhysicalDisplayId displayId, int32_t configId) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    mPendingEvents.push_back(makeConfigChanged(displayId, configId));
+    mCondition.notify_all();
+}
+
 void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
     DisplayEventConsumers consumers;
 
@@ -404,6 +418,7 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
                                      const sp<EventThreadConnection>& connection) const {
     switch (event.header.type) {
         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
             return true;
 
         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
index 3411438..d5e3349 100644 (file)
@@ -112,6 +112,9 @@ public:
 
     virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
 
+    // called when SF changes the active config and apps needs to be notified about the change
+    virtual void onConfigChanged(PhysicalDisplayId displayId, int32_t configId) = 0;
+
     virtual void dump(std::string& result) const = 0;
 
     virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
@@ -153,6 +156,8 @@ public:
 
     void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
 
+    void onConfigChanged(PhysicalDisplayId displayId, int32_t configId) override;
+
     void dump(std::string& result) const override;
 
     void setPhaseOffset(nsecs_t phaseOffset) override;
index 4f846db..990318a 100644 (file)
@@ -153,6 +153,12 @@ void Scheduler::onScreenReleased(const sp<Scheduler::ConnectionHandle>& handle)
     mConnections[handle->id]->thread->onScreenReleased();
 }
 
+void Scheduler::onConfigChanged(const sp<ConnectionHandle>& handle, PhysicalDisplayId displayId,
+                                int32_t configId) {
+    RETURN_IF_INVALID();
+    mConnections[handle->id]->thread->onConfigChanged(displayId, configId);
+}
+
 void Scheduler::dump(const sp<Scheduler::ConnectionHandle>& handle, std::string& result) const {
     RETURN_IF_INVALID();
     mConnections.at(handle->id)->thread->dump(result);
index c566922..7f113e7 100644 (file)
@@ -105,6 +105,10 @@ public:
     // Should be called before the screen is turned off.
     void onScreenReleased(const sp<ConnectionHandle>& handle);
 
+    // Should be called when display config changed
+    void onConfigChanged(const sp<ConnectionHandle>& handle, PhysicalDisplayId displayId,
+                         int32_t configId);
+
     // Should be called when dumpsys command is received.
     void dump(const sp<ConnectionHandle>& handle, std::string& result) const;
 
index fb59259..f651bdf 100644 (file)
@@ -596,11 +596,11 @@ void SurfaceFlinger::bootFinished()
         if (mUse90Hz) {
             mPhaseOffsets->setRefreshRateType(
                     scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
-            setRefreshRateTo(RefreshRateType::PERFORMANCE);
+            setRefreshRateTo(RefreshRateType::PERFORMANCE, ConfigEvent::None);
         } else {
             mPhaseOffsets->setRefreshRateType(
                     scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
-            setRefreshRateTo(RefreshRateType::DEFAULT);
+            setRefreshRateTo(RefreshRateType::DEFAULT, ConfigEvent::None);
         }
     }));
 }
@@ -726,11 +726,11 @@ void SurfaceFlinger::init() {
     if (mUse90Hz) {
         mScheduler->setExpiredIdleTimerCallback([this] {
             Mutex::Autolock lock(mStateLock);
-            setRefreshRateTo(RefreshRateType::DEFAULT);
+            setRefreshRateTo(RefreshRateType::DEFAULT, ConfigEvent::None);
         });
         mScheduler->setResetIdleTimerCallback([this] {
             Mutex::Autolock lock(mStateLock);
-            setRefreshRateTo(RefreshRateType::PERFORMANCE);
+            setRefreshRateTo(RefreshRateType::PERFORMANCE, ConfigEvent::None);
         });
     }
     mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
@@ -938,7 +938,8 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
     return display->getActiveConfig();
 }
 
-void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode) {
+void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode,
+                                            ConfigEvent event) {
     ATRACE_CALL();
 
     Vector<DisplayInfo> configs;
@@ -969,7 +970,7 @@ void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int
     // Don't check against the current mode yet. Worst case we set the desired
     // config twice.
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
-    mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken};
+    mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken, event};
 
     if (!mDesiredActiveConfigChanged) {
         // This is the first time we set the desired
@@ -1002,6 +1003,10 @@ void SurfaceFlinger::setActiveConfigInternal() {
 
     mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
     ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
+    if (mUpcomingActiveConfig.event != ConfigEvent::None) {
+        mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
+                                    mUpcomingActiveConfig.configId);
+    }
 }
 
 bool SurfaceFlinger::performSetActiveConfig() NO_THREAD_SAFETY_ANALYSIS {
@@ -1436,7 +1441,7 @@ bool SurfaceFlinger::isConfigAllowed(const DisplayId& displayId, int32_t config)
     return mAllowedConfigs[displayId]->isConfigAllowed(config);
 }
 
-void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate) {
+void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, ConfigEvent event) {
     mPhaseOffsets->setRefreshRateType(refreshRate);
 
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
@@ -1484,7 +1489,7 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate) {
         // TODO(b/113612090): There should be a better way at determining which config
         // has the right refresh rate.
         if (std::abs(fps - newFps) <= 1) {
-            setDesiredActiveConfig(getInternalDisplayTokenLocked(), i);
+            setDesiredActiveConfig(getInternalDisplayTokenLocked(), i, event);
         }
     }
 }
@@ -5781,7 +5786,7 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal(
                 // we may want to enhance this logic to pick a similar config
                 // to the current one
                 ALOGV("Old config is not allowed - switching to config %d", i);
-                setDesiredActiveConfig(displayToken, i);
+                setDesiredActiveConfig(displayToken, i, ConfigEvent::Changed);
                 break;
             }
         }
index dd03294..9adfb55 100644 (file)
@@ -523,10 +523,13 @@ private:
     void signalLayerUpdate();
     void signalRefresh();
 
+    enum class ConfigEvent { None, Changed };
+
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays() REQUIRES(mStateLock);
     // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
-    void setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
+    void setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode, ConfigEvent event)
+            REQUIRES(mStateLock);
     // Once HWC has returned the present fence, this sets the active config and a new refresh
     // rate in SF. It also triggers HWC vsync.
     void setActiveConfigInternal() REQUIRES(mStateLock);
@@ -811,7 +814,8 @@ private:
 
     // Sets the refresh rate by switching active configs, if they are available for
     // the desired refresh rate.
-    void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType) REQUIRES(mStateLock);
+    void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType, ConfigEvent event)
+            REQUIRES(mStateLock);
 
     bool isConfigAllowed(const DisplayId& displayId, int32_t config);
 
@@ -1116,6 +1120,7 @@ private:
     struct ActiveConfigInfo {
         int configId;
         sp<IBinder> displayToken;
+        ConfigEvent event;
 
         bool operator!=(const ActiveConfigInfo& other) const {
             if (configId != other.configId) {
index e499ff5..406ec81 100644 (file)
@@ -81,6 +81,8 @@ protected:
     void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
     void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
                                                 bool expectedConnected);
+    void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
+                                                      int32_t expectedConfigId);
 
     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
@@ -212,6 +214,16 @@ void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId e
     EXPECT_EQ(expectedConnected, event.hotplug.connected);
 }
 
+void EventThreadTest::expectConfigChangedEventReceivedByConnection(
+        PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId) {
+    auto args = mConnectionEventCallRecorder.waitForCall();
+    ASSERT_TRUE(args.has_value());
+    const auto& event = std::get<0>(args.value());
+    EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, event.header.type);
+    EXPECT_EQ(expectedDisplayId, event.header.displayId);
+    EXPECT_EQ(expectedConfigId, event.config.configId);
+}
+
 namespace {
 
 /* ------------------------------------------------------------------------
@@ -448,5 +460,15 @@ TEST_F(EventThreadTest, postHotplugExternalConnect) {
     expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, true);
 }
 
+TEST_F(EventThreadTest, postConfigChangedPrimary) {
+    mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 7);
+    expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7);
+}
+
+TEST_F(EventThreadTest, postConfigChangedExternal) {
+    mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, 5);
+    expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5);
+}
+
 } // namespace
 } // namespace android
index 5edee6e..cb4a300 100644 (file)
@@ -33,6 +33,7 @@ public:
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
     MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
+    MOCK_METHOD2(onConfigChanged, void(PhysicalDisplayId, int32_t));
     MOCK_CONST_METHOD1(dump, void(std::string&));
     MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset));
     MOCK_METHOD1(registerDisplayEventConnection,