Loading services/surfaceflinger/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -138,8 +138,9 @@ filegroup { "LayerVector.cpp", "MonitoredProducer.cpp", "NativeWindowSurface.cpp", "RenderArea.cpp", "RefreshRateOverlay.cpp", "RegionSamplingThread.cpp", "RenderArea.cpp", "Scheduler/DispSync.cpp", "Scheduler/DispSyncSource.cpp", "Scheduler/EventControlThread.cpp", Loading services/surfaceflinger/RefreshRateOverlay.cpp 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "RefreshRateOverlay.h" #include "Client.h" #include "Layer.h" namespace android { using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) : mFlinger(flinger), mClient(new Client(&mFlinger)) { createLayer(); } bool RefreshRateOverlay::createLayer() { const status_t ret = mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor, LayerMetadata(), &mIBinder, &mGbp, &mLayer); if (ret) { ALOGE("failed to color layer"); return false; } mLayer = mClient->getLayerUser(mIBinder); mLayer->setCrop_legacy(Rect(0, 0, 200, 100), true); mLayer->setLayer(INT32_MAX - 2); return true; } void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) { const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED; mLayer->setColor(color); mFlinger.setTransactionFlags(eTransactionMask); } }; // namespace android services/surfaceflinger/RefreshRateOverlay.h 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "SurfaceFlinger.h" namespace android { using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger& flinger); void changeRefreshRate(RefreshRateType type); private: bool createLayer(); SurfaceFlinger& mFlinger; sp<Client> mClient; sp<Layer> mLayer; sp<IBinder> mIBinder; sp<IGraphicBufferProducer> mGbp; const half3 RED = half3(1.0f, 0.0f, 0.0f); const half3 GREEN = half3(0.0f, 1.0f, 0.0f); }; }; // namespace android services/surfaceflinger/SurfaceFlinger.cpp +30 −15 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ #include "LayerVector.h" #include "MonitoredProducer.h" #include "NativeWindowSurface.h" #include "RefreshRateOverlay.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" #include "SurfaceInterceptor.h" Loading Loading @@ -128,8 +129,6 @@ using ui::DisplayPrimaries; using ui::Hdr; using ui::RenderIntent; using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; namespace { #pragma clang diagnostic push Loading Loading @@ -942,19 +941,18 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { return display->getActiveConfig(); } void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode, Scheduler::ConfigEvent event) { void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); // Lock is acquired by setRefreshRateTo. const auto display = getDisplayDeviceLocked(displayToken); const auto display = getDisplayDeviceLocked(info.displayToken); if (!display) { ALOGE("Attempt to set active config %d for invalid display token %p", mode, displayToken.get()); ALOGE("Attempt to set active config %d for invalid display token %p", info.configId, info.displayToken.get()); return; } if (display->isVirtual()) { ALOGW("Attempt to set active config %d for virtual display", mode); ALOGW("Attempt to set active config %d for virtual display", info.configId); return; } int currentDisplayPowerMode = display->getPowerMode(); Loading @@ -967,8 +965,9 @@ void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int // config twice. However event generation config might have changed so we need to update it // accordingly std::lock_guard<std::mutex> lock(mActiveConfigLock); const Scheduler::ConfigEvent desiredConfig = mDesiredActiveConfig.event | event; mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken, desiredConfig}; const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event; mDesiredActiveConfig = info; mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig; if (!mDesiredActiveConfigChanged) { // This is the first time we set the desired Loading @@ -979,6 +978,10 @@ void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int } mDesiredActiveConfigChanged = true; ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged); if (mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); } } status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) { Loading Loading @@ -1492,7 +1495,7 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co } mPhaseOffsets->setRefreshRateType(refreshRate); setDesiredActiveConfig(getInternalDisplayTokenLocked(), desiredConfigId, event); setDesiredActiveConfig({refreshRate, desiredConfigId, getInternalDisplayTokenLocked(), event}); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, Loading Loading @@ -5033,9 +5036,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { code == IBinder::SYSPROPS_TRANSACTION) { return OK; } // Numbers from 1000 to 1033 are currently used for backdoors. The code // Numbers from 1000 to 1034 are currently used for backdoors. The code // in onTransact verifies that the user is root, and has access to use SF. if (code >= 1000 && code <= 1033) { if (code >= 1000 && code <= 1034) { ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code); return OK; } Loading Loading @@ -5351,6 +5354,18 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r reply->writeInt32(NO_ERROR); return NO_ERROR; } case 1034: { // TODO(b/129297325): expose this via developer menu option n = data.readInt32(); if (n && !mRefreshRateOverlay) { std::lock_guard<std::mutex> lock(mActiveConfigLock); mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); } else if (!n) { mRefreshRateOverlay.reset(); } return NO_ERROR; } } } return err; Loading Loading @@ -5823,8 +5838,8 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal( for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) { if (iter->second && isConfigAllowed(*displayId, iter->second->configId)) { ALOGV("switching to config %d", iter->second->configId); setDesiredActiveConfig(displayToken, iter->second->configId, Scheduler::ConfigEvent::Changed); setDesiredActiveConfig({iter->first, iter->second->configId, displayToken, Scheduler::ConfigEvent::Changed}); break; } } Loading services/surfaceflinger/SurfaceFlinger.h +28 −16 Original line number Diff line number Diff line Loading @@ -90,6 +90,8 @@ using namespace android::surfaceflinger; namespace android { using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; // --------------------------------------------------------------------------- class Client; Loading @@ -102,6 +104,7 @@ class IGraphicBufferProducer; class IInputFlinger; class InjectVSyncSource; class Layer; class RefreshRateOverlay; class Surface; class SurfaceFlingerBE; class TimeStats; Loading Loading @@ -366,6 +369,7 @@ private: friend class BufferQueueLayer; friend class BufferStateLayer; friend class MonitoredProducer; friend class RefreshRateOverlay; friend class RegionSamplingThread; friend class SurfaceTracing; Loading Loading @@ -528,11 +532,30 @@ private: void signalLayerUpdate(); void signalRefresh(); struct ActiveConfigInfo { RefreshRateType type; int configId; sp<IBinder> displayToken; Scheduler::ConfigEvent event; bool operator!=(const ActiveConfigInfo& other) const { if (type != other.type) { return true; } if (configId != other.configId) { return true; } if (displayToken != other.displayToken) { return true; } return (event != other.event); } }; // 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, Scheduler::ConfigEvent event) REQUIRES(mStateLock); void setDesiredActiveConfig(const ActiveConfigInfo& info) 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); Loading Loading @@ -818,8 +841,7 @@ private: // Sets the refresh rate by switching active configs, if they are available for // the desired refresh rate. void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock); void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock); bool isConfigAllowed(const DisplayId& displayId, int32_t config); Loading Loading @@ -1140,18 +1162,6 @@ private: std::unordered_map<DisplayId, std::unique_ptr<const AllowedDisplayConfigs>> mAllowedConfigs GUARDED_BY(mAllowedConfigsLock); struct ActiveConfigInfo { int configId; sp<IBinder> displayToken; Scheduler::ConfigEvent event; bool operator!=(const ActiveConfigInfo& other) const { if (configId != other.configId) { return true; } return (displayToken != other.displayToken); } }; std::mutex mActiveConfigLock; // This bit is set once we start setting the config. We read from this bit during the // process. If at the end, this bit is different than mDesiredActiveConfig, we restart Loading @@ -1178,6 +1188,8 @@ private: sp<SetInputWindowsListener> mSetInputWindowsListener; bool mPendingSyncInputWindows GUARDED_BY(mStateLock); Hwc2::impl::PowerAdvisor mPowerAdvisor; std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay; }; }; // namespace android Loading Loading
services/surfaceflinger/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -138,8 +138,9 @@ filegroup { "LayerVector.cpp", "MonitoredProducer.cpp", "NativeWindowSurface.cpp", "RenderArea.cpp", "RefreshRateOverlay.cpp", "RegionSamplingThread.cpp", "RenderArea.cpp", "Scheduler/DispSync.cpp", "Scheduler/DispSyncSource.cpp", "Scheduler/EventControlThread.cpp", Loading
services/surfaceflinger/RefreshRateOverlay.cpp 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "RefreshRateOverlay.h" #include "Client.h" #include "Layer.h" namespace android { using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) : mFlinger(flinger), mClient(new Client(&mFlinger)) { createLayer(); } bool RefreshRateOverlay::createLayer() { const status_t ret = mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor, LayerMetadata(), &mIBinder, &mGbp, &mLayer); if (ret) { ALOGE("failed to color layer"); return false; } mLayer = mClient->getLayerUser(mIBinder); mLayer->setCrop_legacy(Rect(0, 0, 200, 100), true); mLayer->setLayer(INT32_MAX - 2); return true; } void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) { const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED; mLayer->setColor(color); mFlinger.setTransactionFlags(eTransactionMask); } }; // namespace android
services/surfaceflinger/RefreshRateOverlay.h 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "SurfaceFlinger.h" namespace android { using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger& flinger); void changeRefreshRate(RefreshRateType type); private: bool createLayer(); SurfaceFlinger& mFlinger; sp<Client> mClient; sp<Layer> mLayer; sp<IBinder> mIBinder; sp<IGraphicBufferProducer> mGbp; const half3 RED = half3(1.0f, 0.0f, 0.0f); const half3 GREEN = half3(0.0f, 1.0f, 0.0f); }; }; // namespace android
services/surfaceflinger/SurfaceFlinger.cpp +30 −15 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ #include "LayerVector.h" #include "MonitoredProducer.h" #include "NativeWindowSurface.h" #include "RefreshRateOverlay.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" #include "SurfaceInterceptor.h" Loading Loading @@ -128,8 +129,6 @@ using ui::DisplayPrimaries; using ui::Hdr; using ui::RenderIntent; using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; namespace { #pragma clang diagnostic push Loading Loading @@ -942,19 +941,18 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { return display->getActiveConfig(); } void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode, Scheduler::ConfigEvent event) { void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); // Lock is acquired by setRefreshRateTo. const auto display = getDisplayDeviceLocked(displayToken); const auto display = getDisplayDeviceLocked(info.displayToken); if (!display) { ALOGE("Attempt to set active config %d for invalid display token %p", mode, displayToken.get()); ALOGE("Attempt to set active config %d for invalid display token %p", info.configId, info.displayToken.get()); return; } if (display->isVirtual()) { ALOGW("Attempt to set active config %d for virtual display", mode); ALOGW("Attempt to set active config %d for virtual display", info.configId); return; } int currentDisplayPowerMode = display->getPowerMode(); Loading @@ -967,8 +965,9 @@ void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int // config twice. However event generation config might have changed so we need to update it // accordingly std::lock_guard<std::mutex> lock(mActiveConfigLock); const Scheduler::ConfigEvent desiredConfig = mDesiredActiveConfig.event | event; mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken, desiredConfig}; const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event; mDesiredActiveConfig = info; mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig; if (!mDesiredActiveConfigChanged) { // This is the first time we set the desired Loading @@ -979,6 +978,10 @@ void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int } mDesiredActiveConfigChanged = true; ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged); if (mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); } } status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) { Loading Loading @@ -1492,7 +1495,7 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co } mPhaseOffsets->setRefreshRateType(refreshRate); setDesiredActiveConfig(getInternalDisplayTokenLocked(), desiredConfigId, event); setDesiredActiveConfig({refreshRate, desiredConfigId, getInternalDisplayTokenLocked(), event}); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, Loading Loading @@ -5033,9 +5036,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { code == IBinder::SYSPROPS_TRANSACTION) { return OK; } // Numbers from 1000 to 1033 are currently used for backdoors. The code // Numbers from 1000 to 1034 are currently used for backdoors. The code // in onTransact verifies that the user is root, and has access to use SF. if (code >= 1000 && code <= 1033) { if (code >= 1000 && code <= 1034) { ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code); return OK; } Loading Loading @@ -5351,6 +5354,18 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r reply->writeInt32(NO_ERROR); return NO_ERROR; } case 1034: { // TODO(b/129297325): expose this via developer menu option n = data.readInt32(); if (n && !mRefreshRateOverlay) { std::lock_guard<std::mutex> lock(mActiveConfigLock); mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); } else if (!n) { mRefreshRateOverlay.reset(); } return NO_ERROR; } } } return err; Loading Loading @@ -5823,8 +5838,8 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal( for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) { if (iter->second && isConfigAllowed(*displayId, iter->second->configId)) { ALOGV("switching to config %d", iter->second->configId); setDesiredActiveConfig(displayToken, iter->second->configId, Scheduler::ConfigEvent::Changed); setDesiredActiveConfig({iter->first, iter->second->configId, displayToken, Scheduler::ConfigEvent::Changed}); break; } } Loading
services/surfaceflinger/SurfaceFlinger.h +28 −16 Original line number Diff line number Diff line Loading @@ -90,6 +90,8 @@ using namespace android::surfaceflinger; namespace android { using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; // --------------------------------------------------------------------------- class Client; Loading @@ -102,6 +104,7 @@ class IGraphicBufferProducer; class IInputFlinger; class InjectVSyncSource; class Layer; class RefreshRateOverlay; class Surface; class SurfaceFlingerBE; class TimeStats; Loading Loading @@ -366,6 +369,7 @@ private: friend class BufferQueueLayer; friend class BufferStateLayer; friend class MonitoredProducer; friend class RefreshRateOverlay; friend class RegionSamplingThread; friend class SurfaceTracing; Loading Loading @@ -528,11 +532,30 @@ private: void signalLayerUpdate(); void signalRefresh(); struct ActiveConfigInfo { RefreshRateType type; int configId; sp<IBinder> displayToken; Scheduler::ConfigEvent event; bool operator!=(const ActiveConfigInfo& other) const { if (type != other.type) { return true; } if (configId != other.configId) { return true; } if (displayToken != other.displayToken) { return true; } return (event != other.event); } }; // 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, Scheduler::ConfigEvent event) REQUIRES(mStateLock); void setDesiredActiveConfig(const ActiveConfigInfo& info) 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); Loading Loading @@ -818,8 +841,7 @@ private: // Sets the refresh rate by switching active configs, if they are available for // the desired refresh rate. void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock); void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock); bool isConfigAllowed(const DisplayId& displayId, int32_t config); Loading Loading @@ -1140,18 +1162,6 @@ private: std::unordered_map<DisplayId, std::unique_ptr<const AllowedDisplayConfigs>> mAllowedConfigs GUARDED_BY(mAllowedConfigsLock); struct ActiveConfigInfo { int configId; sp<IBinder> displayToken; Scheduler::ConfigEvent event; bool operator!=(const ActiveConfigInfo& other) const { if (configId != other.configId) { return true; } return (displayToken != other.displayToken); } }; std::mutex mActiveConfigLock; // This bit is set once we start setting the config. We read from this bit during the // process. If at the end, this bit is different than mDesiredActiveConfig, we restart Loading @@ -1178,6 +1188,8 @@ private: sp<SetInputWindowsListener> mSetInputWindowsListener; bool mPendingSyncInputWindows GUARDED_BY(mStateLock); Hwc2::impl::PowerAdvisor mPowerAdvisor; std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay; }; }; // namespace android Loading