SF: default display is active display
For devices with multiple internal displays, choose the internal
display the is powered on (if any) to be the default display that
would be used mainly for vsync tracking.
Bug: 187539899
Test: SF unit tests
Change-Id: Icc305cdeec1c8a04729f00ff795dfbb806d8f72c
Merged-In: Icc305cdeec1c8a04729f00ff795dfbb806d8f72c
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 915dba3..95d58ab 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -71,7 +71,7 @@
void cleanupPostRender() override;
int getContextPriority() override;
bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
- void onPrimaryDisplaySizeChanged(ui::Size size) override {}
+ void onActiveDisplaySizeChanged(ui::Size size) override {}
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
// Creates an output image for rendering to
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index ac0affb..9fdf4d1 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -129,9 +129,9 @@
// Attempt to switch RenderEngine into and out of protectedContext mode
virtual bool useProtectedContext(bool useProtectedContext) = 0;
- // Notify RenderEngine of changes to the dimensions of the primary display
+ // Notify RenderEngine of changes to the dimensions of the active display
// so that it can configure its internal caches accordingly.
- virtual void onPrimaryDisplaySizeChanged(ui::Size size) = 0;
+ virtual void onActiveDisplaySizeChanged(ui::Size size) = 0;
// Renders layers for a particular display via GPU composition. This method
// should be called for every display that needs to be rendered via the GPU.
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 0175af3..c0b1c6f 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -54,7 +54,7 @@
MOCK_METHOD0(cleanFramebufferCache, void());
MOCK_METHOD0(getContextPriority, int());
MOCK_METHOD0(supportsBackgroundBlur, bool());
- MOCK_METHOD1(onPrimaryDisplaySizeChanged, void(ui::Size));
+ MOCK_METHOD1(onActiveDisplaySizeChanged, void(ui::Size));
protected:
// mock renderengine still needs to implement these, but callers should never need to call them.
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index c7356ea..a963819 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -1401,7 +1401,7 @@
return value;
}
-void SkiaGLRenderEngine::onPrimaryDisplaySizeChanged(ui::Size size) {
+void SkiaGLRenderEngine::onActiveDisplaySizeChanged(ui::Size size) {
// This cache multiplier was selected based on review of cache sizes relative
// to the screen resolution. Looking at the worst case memory needed by blur (~1.5x),
// shadows (~1x), and general data structures (e.g. vertex buffers) we selected this as a
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index b30355b..48aa276 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -67,7 +67,7 @@
bool useProtectedContext(bool useProtectedContext) override;
bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
void assertShadersCompiled(int numShaders) override;
- void onPrimaryDisplaySizeChanged(ui::Size size) override;
+ void onActiveDisplaySizeChanged(ui::Size size) override;
int reportShadersCompiled() override;
protected:
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index ea3871f..c09ea9c 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -354,14 +354,14 @@
return mRenderEngine->supportsBackgroundBlur();
}
-void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
+void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
// This function is designed so it can run asynchronously, so we do not need to wait
// for the futures.
{
std::lock_guard lock(mThreadMutex);
mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
- instance.onPrimaryDisplaySizeChanged(size);
+ ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
+ instance.onActiveDisplaySizeChanged(size);
});
}
mCondition.notify_one();
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 9b523b2..71d46c1 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -65,7 +65,7 @@
void cleanFramebufferCache() override;
int getContextPriority() override;
bool supportsBackgroundBlur() override;
- void onPrimaryDisplaySizeChanged(ui::Size size) override;
+ void onActiveDisplaySizeChanged(ui::Size size) override;
protected:
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c391901..517f848 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -217,7 +217,7 @@
}
void DisplayDevice::setLayerStack(ui::LayerStack stack) {
- mCompositionDisplay->setLayerStackFilter(stack, isPrimary());
+ mCompositionDisplay->setLayerStackFilter(stack, isInternal());
}
void DisplayDevice::setFlags(uint32_t flags) {
@@ -266,7 +266,7 @@
std::string DisplayDevice::getDebugName() const {
const char* type = "virtual";
if (mConnectionType) {
- type = *mConnectionType == ui::DisplayConnectionType::Internal ? "internal" : "external";
+ type = isInternal() ? "internal" : "external";
}
return base::StringPrintf("DisplayDevice{%s, %s%s, \"%s\"}", to_string(getId()).c_str(), type,
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 70dcc1e..e5fe067 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -79,6 +79,9 @@
bool isVirtual() const { return !mConnectionType; }
bool isPrimary() const { return mIsPrimary; }
+ bool isInternal() const {
+ return !isVirtual() && mConnectionType == ui::DisplayConnectionType::Internal;
+ }
// isSecure indicates whether this display can be trusted to display
// secure surfaces.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 6d6e3c2..384e4e9 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -893,7 +893,7 @@
}
}
-void Scheduler::onPrimaryDisplayAreaChanged(uint32_t displayArea) {
+void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) {
mLayerHistory->setDisplayArea(displayArea);
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 30a3253..7a2fdb5 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -165,7 +165,7 @@
void onDisplayRefreshed(nsecs_t timestamp);
// Notifies the scheduler when the display size has changed. Called from SF's main thread
- void onPrimaryDisplayAreaChanged(uint32_t displayArea);
+ void onActiveDisplayAreaChanged(uint32_t displayArea);
size_t getEventThreadConnectionCount(ConnectionHandle handle);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 194e698..18cb0c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -632,9 +632,7 @@
mVirtualDisplayIdGenerators.gpu.releaseId(*id);
}
-std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIds() const {
- Mutex::Autolock lock(mStateLock);
-
+std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIdsLocked() const {
const auto internalDisplayId = getInternalDisplayIdLocked();
if (!internalDisplayId) {
return {};
@@ -837,7 +835,7 @@
}
}
- getRenderEngine().onPrimaryDisplaySizeChanged(display->getSize());
+ onActiveDisplaySizeChanged(display);
// Inform native graphics APIs whether the present timestamp is supported:
@@ -2335,7 +2333,7 @@
mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence);
mTransactionCallbackInvoker.sendCallbacks();
- if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
+ if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON &&
mPreviousPresentFences[0].fenceTime->isValid()) {
mScheduler->addPresentFence(mPreviousPresentFences[0].fenceTime);
}
@@ -2785,11 +2783,6 @@
if (!state.isVirtual()) {
dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
}
-
- if (display->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(display->getWidth() * display->getHeight());
- getRenderEngine().onPrimaryDisplaySizeChanged(display->getSize());
- }
}
void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) {
@@ -2854,16 +2847,8 @@
// TODO(b/175678251) Call a listener instead.
if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
- mRefreshRateConfigs->updateDisplayModes(currentState.physical->supportedModes,
- currentState.physical->activeMode->getId());
- mVsyncConfiguration->reset();
- const Fps refreshRate = currentState.physical->activeMode->getFps();
- updatePhaseConfiguration(refreshRate);
- mRefreshRateStats->setRefreshRate(refreshRate);
-
- if (mRefreshRateOverlay) {
- mRefreshRateOverlay->reset();
- }
+ updateInternalDisplayVsyncLocked(currentState.physical->supportedModes,
+ currentState.physical->activeMode->getId());
}
}
return;
@@ -2889,8 +2874,8 @@
currentState.height != drawingState.height) {
display->setDisplaySize(currentState.width, currentState.height);
- if (display->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height);
+ if (isDisplayActiveLocked(display)) {
+ onActiveDisplaySizeChanged(display);
}
if (mRefreshRateOverlay) {
@@ -2899,6 +2884,17 @@
}
}
}
+void SurfaceFlinger::updateInternalDisplayVsyncLocked(const DisplayModes& modes,
+ DisplayModeId currentModeId) {
+ mRefreshRateConfigs->updateDisplayModes(modes, currentModeId);
+ mVsyncConfiguration->reset();
+ const Fps refreshRate = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+ updatePhaseConfiguration(refreshRate);
+ mRefreshRateStats->setRefreshRate(refreshRate);
+ if (mRefreshRateOverlay) {
+ mRefreshRateOverlay->reset();
+ }
+}
void SurfaceFlinger::processDisplayChangesLocked() {
// here we take advantage of Vector's copy-on-write semantics to
@@ -4555,6 +4551,11 @@
}
const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
if (currentMode == hal::PowerMode::OFF) {
+ const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken);
+ if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) {
+ mActiveDisplayToken = display->getDisplayToken();
+ onActiveDisplayChangedLocked(getDisplayDeviceLocked(mActiveDisplayToken));
+ }
// Keep uclamp in a separate syscall and set it before changing to RT due to b/190237315.
// We can merge the syscall later.
if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
@@ -4564,7 +4565,7 @@
ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
}
getHwComposer().setPowerMode(displayId, mode);
- if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
+ if (display->isInternal() && mode != hal::PowerMode::DOZE_SUSPEND) {
getHwComposer().setVsyncEnabled(displayId, mHWCVsyncPendingState);
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
@@ -4581,7 +4582,7 @@
if (SurfaceFlinger::setSchedAttr(false) != NO_ERROR) {
ALOGW("Couldn't set uclamp.min on display off: %s\n", strerror(errno));
}
- if (display->isPrimary() && currentMode != hal::PowerMode::DOZE_SUSPEND) {
+ if (display->isInternal() && currentMode != hal::PowerMode::DOZE_SUSPEND) {
mScheduler->disableHardwareVsync(true);
mScheduler->onScreenReleased(mAppConnectionHandle);
}
@@ -4595,13 +4596,13 @@
} else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) {
// Update display while dozing
getHwComposer().setPowerMode(displayId, mode);
- if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
+ if (display->isInternal() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
}
} else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
- if (display->isPrimary()) {
+ if (display->isInternal()) {
mScheduler->disableHardwareVsync(true);
mScheduler->onScreenReleased(mAppConnectionHandle);
}
@@ -4611,7 +4612,7 @@
getHwComposer().setPowerMode(displayId, mode);
}
- if (display->isPrimary()) {
+ if (display->isInternal()) {
mTimeStats->setPowerMode(mode);
mRefreshRateStats->setPowerMode(mode);
mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON);
@@ -5686,7 +5687,7 @@
return std::make_optional<PhysicalDisplayId>(inputDisplayId);
}
- return getInternalDisplayId();
+ return getDefaultDisplayDevice()->getPhysicalId();
}();
if (!displayId) {
@@ -6459,8 +6460,10 @@
const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {
Mutex::Autolock lock(mStateLock);
- LOG_ALWAYS_FATAL_IF(!display->isPrimary() && overridePolicy,
- "Can only set override policy on the primary display");
+ const bool isDefaultDisplay = display == getDefaultDisplayDeviceLocked();
+
+ LOG_ALWAYS_FATAL_IF(!isDefaultDisplay && overridePolicy,
+ "Can only set override policy on the default display");
LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy");
if (mDebugDisplayModeSetByBackdoor) {
@@ -6468,11 +6471,11 @@
return NO_ERROR;
}
- if (!display->isPrimary()) {
- // TODO(b/144711714): For non-primary displays we should be able to set an active mode
+ if (!isDefaultDisplay) {
+ // TODO(b/144711714): For non-default displays we should be able to set an active mode
// as well. For now, just call directly to initiateModeChange but ideally
// it should go thru setDesiredActiveMode, similar to primary display.
- ALOGV("%s for non-primary display", __func__);
+ ALOGV("%s for non-default display", __func__);
const auto displayId = display->getPhysicalId();
hal::VsyncPeriodChangeConstraints constraints;
@@ -6590,7 +6593,7 @@
return NAME_NOT_FOUND;
}
- if (display->isPrimary()) {
+ if (display == getDefaultDisplayDeviceLocked()) {
scheduler::RefreshRateConfigs::Policy policy =
mRefreshRateConfigs->getDisplayManagerPolicy();
*outDefaultMode = policy.defaultMode.value();
@@ -6984,6 +6987,27 @@
mRegionSamplingThread->onCompositionComplete(mEventQueue->nextExpectedInvalidate());
}
+void SurfaceFlinger::onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay) {
+ mScheduler->onActiveDisplayAreaChanged(activeDisplay->getWidth() * activeDisplay->getHeight());
+ getRenderEngine().onActiveDisplaySizeChanged(activeDisplay->getSize());
+}
+
+void SurfaceFlinger::onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay) {
+ ATRACE_CALL();
+
+ if (!activeDisplay) {
+ ALOGE("%s: activeDisplay is null", __func__);
+ return;
+ }
+ updateInternalDisplayVsyncLocked(activeDisplay->getSupportedModes(),
+ activeDisplay->getActiveMode()->getId());
+ onActiveDisplaySizeChanged(activeDisplay);
+ if (mRefreshRateOverlay) {
+ mRefreshRateOverlay->setViewport(activeDisplay->getSize());
+ mRefreshRateOverlay->changeRefreshRate(activeDisplay->getActiveMode()->getFps());
+ }
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6d9767e..338aa18 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -609,7 +609,10 @@
sp<ISurfaceComposerClient> createConnection() override;
sp<IBinder> createDisplay(const String8& displayName, bool secure) override;
void destroyDisplay(const sp<IBinder>& displayToken) override;
- std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override;
+ std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override EXCLUDES(mStateLock) {
+ Mutex::Autolock lock(mStateLock);
+ return getPhysicalDisplayIdsLocked();
+ }
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override;
status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
const Vector<ComposerState>& state,
@@ -961,6 +964,11 @@
}
sp<DisplayDevice> getDefaultDisplayDeviceLocked() REQUIRES(mStateLock) {
+ if (const auto display = getDisplayDeviceLocked(mActiveDisplayToken)) {
+ return display;
+ }
+ // The active display is outdated, fall back to the internal display
+ mActiveDisplayToken.clear();
if (const auto token = getInternalDisplayTokenLocked()) {
return getDisplayDeviceLocked(token);
}
@@ -986,12 +994,18 @@
return findDisplay([id](const auto& display) { return display.getId() == id; });
}
+ std::vector<PhysicalDisplayId> getPhysicalDisplayIdsLocked() const REQUIRES(mStateLock);
+
// mark a region of a layer stack dirty. this updates the dirty
// region of all screens presenting this layer stack.
void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
sp<DisplayDevice> getDisplayWithInputByLayer(Layer* layer) const REQUIRES(mStateLock);
+ bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) REQUIRES(mStateLock) {
+ return display->getDisplayToken() == mActiveDisplayToken;
+ }
+
/*
* H/W composer
*/
@@ -1114,6 +1128,10 @@
REQUIRES(mStateLock);
void releaseVirtualDisplay(VirtualDisplayId);
+ void onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay) REQUIRES(mStateLock);
+
+ void onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay);
+
/*
* Debugging & dumpsys
*/
@@ -1193,6 +1211,9 @@
std::chrono::nanoseconds presentLatency);
int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;
+ void updateInternalDisplayVsyncLocked(const DisplayModes& modes, DisplayModeId currentModeId)
+ REQUIRES(mStateLock);
+
sp<StartPropertySetThread> mStartPropertySetThread;
surfaceflinger::Factory& mFactory;
@@ -1481,6 +1502,8 @@
void scheduleRegionSamplingThread();
void notifyRegionSamplingThread();
+
+ wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock);
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index f680d80..e51db84 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -171,7 +171,7 @@
mScheduler->setDisplayPowerState(kPowerStateNormal);
constexpr uint32_t kDisplayArea = 999'999;
- mScheduler->onPrimaryDisplayAreaChanged(kDisplayArea);
+ mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
EXPECT_CALL(mSchedulerCallback, changeRefreshRate(_, _)).Times(0);
mScheduler->chooseRefreshRateForContent();
@@ -235,7 +235,7 @@
mScheduler->setDisplayPowerState(kPowerStateNormal);
constexpr uint32_t kDisplayArea = 999'999;
- mScheduler->onPrimaryDisplayAreaChanged(kDisplayArea);
+ mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
EXPECT_CALL(mSchedulerCallback, changeRefreshRate(Is120Hz(), _)).Times(1);
mScheduler->chooseRefreshRateForContent();