SF: Revamp frequencyScale backdoor
Update the frequencyScale backdoor (1029) to do a primary
display hot unplug-plug so that the updated frequency makes
it to the DisplayManager
Test: adb shell service call SurfaceFlinger 1029 i32 2 i32 3
Change-Id: Id93a5946ee19fbe9925789ba3294cbf213a52c30
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index ef31908..a32ff6e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -184,6 +184,7 @@
auto newDisplay = std::make_unique<Display>(
*mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
+ newDisplay->setFrequencyScaleParameters(mFrequencyScaler);
newDisplay->setConnected(true);
mDisplays.emplace(displayId, std::move(newDisplay));
} else if (connection == Connection::Disconnected) {
@@ -223,6 +224,14 @@
return static_cast<Error>(mComposer->executeCommands());
}
+void Device::setDisplayFrequencyScaleParameters(Device::FrequencyScaler frequencyScaler) {
+ mFrequencyScaler = frequencyScaler;
+}
+
+Device::FrequencyScaler Device::getDisplayFrequencyScaleParameters() {
+ return mFrequencyScaler;
+}
+
// Display methods
Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
@@ -262,6 +271,7 @@
mWidth(-1),
mHeight(-1),
mVsyncPeriod(-1),
+ mFrequencyScaler(display.mFrequencyScaler),
mDpiX(-1),
mDpiY(-1) {}
@@ -701,6 +711,10 @@
mIsConnected = connected;
}
+void Display::setFrequencyScaleParameters(Device::FrequencyScaler frequencyScaler) {
+ mFrequencyScaler = frequencyScaler;
+}
+
int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
{
int32_t value = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index e0d6ecc..a8f24d6 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -85,6 +85,11 @@
public:
explicit Device(std::unique_ptr<android::Hwc2::Composer> composer);
+ struct FrequencyScaler {
+ int32_t multiplier = 1;
+ int32_t divisor = 1;
+ };
+
void registerCallback(ComposerCallback* callback, int32_t sequenceId);
// Required by HWC2
@@ -116,6 +121,9 @@
// This method provides an explicit way to flush state changes to HWC.
Error flushCommands();
+ void setDisplayFrequencyScaleParameters(FrequencyScaler frequecyScaler);
+ FrequencyScaler getDisplayFrequencyScaleParameters();
+
private:
// Initialization methods
@@ -126,6 +134,7 @@
std::unordered_set<Capability> mCapabilities;
std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
android::Hwc2::impl::PowerAdvisor mPowerAdvisor;
+ FrequencyScaler mFrequencyScaler;
bool mRegisteredCallback = false;
};
@@ -161,8 +170,6 @@
}
Builder& setVsyncPeriod(int32_t vsyncPeriod) {
mConfig->mVsyncPeriod = vsyncPeriod;
- mConfig->mPeriodMultiplier = 1;
- mConfig->mPeriodDivisor = 1;
return *this;
}
Builder& setDpiX(int32_t dpiX) {
@@ -193,11 +200,7 @@
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
nsecs_t getVsyncPeriod() const {
- return mVsyncPeriod * mPeriodMultiplier / mPeriodDivisor; }
- void scalePanelFrequency(int32_t multiplier, int32_t divisor) const {
- mPeriodMultiplier = multiplier;
- mPeriodDivisor = divisor;
- }
+ return mVsyncPeriod * mFrequencyScaler.multiplier / mFrequencyScaler.divisor; }
float getDpiX() const { return mDpiX; }
float getDpiY() const { return mDpiY; }
@@ -210,8 +213,7 @@
int32_t mWidth;
int32_t mHeight;
nsecs_t mVsyncPeriod;
- mutable int32_t mPeriodMultiplier;
- mutable int32_t mPeriodDivisor;
+ Device::FrequencyScaler mFrequencyScaler;
float mDpiX;
float mDpiY;
};
@@ -279,6 +281,7 @@
hwc2_display_t getId() const { return mId; }
bool isConnected() const { return mIsConnected; }
void setConnected(bool connected); // For use by Device only
+ void setFrequencyScaleParameters(Device::FrequencyScaler frequencyScaler);
private:
int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
@@ -303,6 +306,7 @@
hwc2_display_t mId;
bool mIsConnected;
DisplayType mType;
+ Device::FrequencyScaler mFrequencyScaler;
std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
};
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index bf8905a..630cc0b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -807,4 +807,15 @@
return mDisplayData[displayId].hwcDisplay->getId();
}
+void HWComposer::setDisplayFrequencyScaleParameters(
+ HWC2::Device::FrequencyScaler frequencyScaler)
+{
+ mHwcDevice->setDisplayFrequencyScaleParameters(frequencyScaler);
+}
+
+HWC2::Device::FrequencyScaler HWComposer::getDisplayFrequencyScaleParameters()
+{
+ return mHwcDevice->getDisplayFrequencyScaleParameters();
+}
+
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3c5efea..9e01626 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -184,6 +184,14 @@
android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
std::optional<hwc2_display_t> getHwcDisplayId(int32_t displayId) const;
+
+ // ------------------------------------------------------------------------
+ // These functions set and get the frequencyScaler. The frequencyScaler holds
+ // a multiplier and divisor for virtually scaling the panel frequency in
+ // software. This is used to simulate different panel frequencies when
+ // panel hardware is not available.
+ void setDisplayFrequencyScaleParameters(HWC2::Device::FrequencyScaler frequencyScaler);
+ HWC2::Device::FrequencyScaler getDisplayFrequencyScaleParameters();
private:
// For unit tests
friend TestableSurfaceFlinger;
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 9d9acd3..54a1b51 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -521,16 +521,18 @@
mThread->updateModel(mPeriod, mPhase, mReferenceTime);
}
-void DispSync::scalePeriod(uint32_t multiplier, uint32_t divisor) {
+void DispSync::scalePeriod(HWC2::Device::FrequencyScaler frequencyScaler) {
Mutex::Autolock lock(mMutex);
// if only 1 of the properties is updated, we will get to this
// point "attempting" to set the scale to 1 when it is already
// 1. Check that special case so that we don't do a useless
// update of the model.
- if ((multiplier == 1) && (divisor == 1) && (mPeriod == mPeriodBase)) return;
+ if ((frequencyScaler.multiplier == 1) &&
+ (frequencyScaler.divisor == 1) &&
+ (mPeriod == mPeriodBase)) return;
- mPeriod = mPeriodBase * multiplier / divisor;
+ mPeriod = mPeriodBase * frequencyScaler.multiplier / frequencyScaler.divisor;
mThread->updateModel(mPeriod, mPhase, mReferenceTime);
}
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index 183966f..b3aef2d 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -24,6 +24,7 @@
#include <utils/Timers.h>
#include <ui/FenceTime.h>
+#include <DisplayHardware/HWC2.h>
#include <memory>
@@ -48,7 +49,7 @@
virtual bool addResyncSample(nsecs_t timestamp) = 0;
virtual void endResync() = 0;
virtual void setPeriod(nsecs_t period) = 0;
- virtual void scalePeriod(const uint32_t multiplier, uint32_t divisor) = 0;
+ virtual void scalePeriod(HWC2::Device::FrequencyScaler) = 0;
virtual nsecs_t getPeriod() = 0;
virtual void setRefreshSkipCount(int count) = 0;
virtual status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) = 0;
@@ -122,7 +123,7 @@
// scale the vsync event model's period. The function is added
// for an experimental test mode and should not be used outside
// of that purpose.
- void scalePeriod(const uint32_t multiplier, uint32_t divisor);
+ void scalePeriod(HWC2::Device::FrequencyScaler frequencyScaler);
// The getPeriod method returns the current vsync period.
nsecs_t getPeriod() override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a779289..a6320a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4830,27 +4830,40 @@
// Code 1029 is an experimental feature that allows applications to
// simulate a high frequency panel by setting a multiplier and divisor
// on the VSYNC-sf clock. If either the multiplier or divisor are
- // 0, then the code will set both to 1 to return the VSYNC-sf clock
- // to it's normal frequency.
- int multiplier = data.readInt32();
- int divisor = data.readInt32();
+ // 0, then the code simply return the current multiplier and divisor.
+ HWC2::Device::FrequencyScaler frequencyScaler;
+ frequencyScaler.multiplier = data.readInt32();
+ frequencyScaler.divisor = data.readInt32();
- if ((multiplier == 0) || (divisor == 0)) {
- multiplier = 1;
- divisor = 1;
+ if ((frequencyScaler.multiplier == 0) || (frequencyScaler.divisor == 0)) {
+ frequencyScaler = getBE().mHwc->getDisplayFrequencyScaleParameters();
+ reply->writeInt32(frequencyScaler.multiplier);
+ reply->writeInt32(frequencyScaler.divisor);
+ return NO_ERROR;
}
- if ((multiplier == 1) && (divisor == 1)) {
+ if ((frequencyScaler.multiplier == 1) && (frequencyScaler.divisor == 1)) {
enableHardwareVsync();
} else {
disableHardwareVsync(true);
}
- getBE().mHwc->getActiveConfig(DisplayDevice::DISPLAY_PRIMARY)
- ->scalePanelFrequency(multiplier, divisor);
- mPrimaryDispSync->scalePeriod(multiplier, divisor);
+ mPrimaryDispSync->scalePeriod(frequencyScaler);
+ getBE().mHwc->setDisplayFrequencyScaleParameters(frequencyScaler);
- ATRACE_INT("PeriodMultiplier", multiplier);
- ATRACE_INT("PeriodDivisor", divisor);
+ ATRACE_INT("PeriodMultiplier", frequencyScaler.multiplier);
+ ATRACE_INT("PeriodDivisor", frequencyScaler.divisor);
+
+ const hwc2_display_t hwcDisplayId = getBE().mHwc->getActiveConfig(
+ DisplayDevice::DISPLAY_PRIMARY)->getDisplayId();
+
+ onHotplugReceived(getBE().mComposerSequenceId,
+ hwcDisplayId, HWC2::Connection::Disconnected);
+ onHotplugReceived(getBE().mComposerSequenceId,
+ hwcDisplayId, HWC2::Connection::Connected);
+ frequencyScaler = getBE().mHwc->getDisplayFrequencyScaleParameters();
+ reply->writeInt32(frequencyScaler.multiplier);
+ reply->writeInt32(frequencyScaler.divisor);
+
return NO_ERROR;
}
// Is device color managed?
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index 06a6b69..46d6558 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -35,7 +35,7 @@
MOCK_METHOD1(addResyncSample, bool(nsecs_t));
MOCK_METHOD0(endResync, void());
MOCK_METHOD1(setPeriod, void(nsecs_t));
- MOCK_METHOD2(scalePeriod, void(uint32_t, uint32_t));
+ MOCK_METHOD1(scalePeriod, void(HWC2::Device::FrequencyScaler));
MOCK_METHOD0(getPeriod, nsecs_t());
MOCK_METHOD1(setRefreshSkipCount, void(int));
MOCK_METHOD3(addEventListener, status_t(const char*, nsecs_t, Callback*));