2) SF-DM Generalization of Refresh Rates: Adding config variable and getter methods
Test: Logs. Unittest.
Bug: 142507213
Change-Id: Ibf93cfc2d88c4dd7764ba62d1b2c948fec534da8
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index fd0c8d42..546757b 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -878,6 +878,33 @@
return reply.readInt32();
}
+ virtual status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
+ std::vector<int32_t>* outAllowedConfigs) {
+ if (!outAllowedConfigs) return BAD_VALUE;
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getAllowedDisplayConfigs failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(displayToken);
+ if (result != NO_ERROR) {
+ ALOGE("getAllowedDisplayConfigs failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_ALLOWED_DISPLAY_CONFIGS, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getAllowedDisplayConfigs failed to transact: %d", result);
+ return result;
+ }
+ result = reply.readInt32Vector(outAllowedConfigs);
+ if (result != NO_ERROR) {
+ ALOGE("getAllowedDisplayConfigs failed to readInt32Vector: %d", result);
+ return result;
+ }
+ return reply.readInt32();
+ }
+
virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t defaultModeId, float minRefreshRate,
float maxRefreshRate) {
@@ -917,28 +944,41 @@
return reply.readInt32();
}
- virtual status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
- std::vector<int32_t>* outAllowedConfigs) {
- if (!outAllowedConfigs) return BAD_VALUE;
+ virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultModeId,
+ float* outMinRefreshRate,
+ float* outMaxRefreshRate) {
+ if (!outDefaultModeId || !outMinRefreshRate || !outMaxRefreshRate) return BAD_VALUE;
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
- ALOGE("getAllowedDisplayConfigs failed to writeInterfaceToken: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs failed to writeInterfaceToken: %d", result);
return result;
}
result = data.writeStrongBinder(displayToken);
if (result != NO_ERROR) {
- ALOGE("getAllowedDisplayConfigs failed to writeStrongBinder: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs failed to writeStrongBinder: %d", result);
return result;
}
- result = remote()->transact(BnSurfaceComposer::GET_ALLOWED_DISPLAY_CONFIGS, data, &reply);
+ result = remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_CONFIG_SPECS, data,
+ &reply);
if (result != NO_ERROR) {
- ALOGE("getAllowedDisplayConfigs failed to transact: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs failed to transact: %d", result);
return result;
}
- result = reply.readInt32Vector(outAllowedConfigs);
+ result = reply.readInt32(outDefaultModeId);
if (result != NO_ERROR) {
- ALOGE("getAllowedDisplayConfigs failed to readInt32Vector: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs failed to read defaultModeId: %d", result);
+ return result;
+ }
+ result = reply.readFloat(outMinRefreshRate);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs failed to read minRefreshRate: %d", result);
+ return result;
+ }
+ result = reply.readFloat(outMaxRefreshRate);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs failed to read maxRefreshRate: %d", result);
return result;
}
return reply.readInt32();
@@ -1654,6 +1694,40 @@
reply->writeInt32(result);
return result;
}
+ case GET_DESIRED_DISPLAY_CONFIG_SPECS: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> displayToken = data.readStrongBinder();
+ int32_t defaultModeId;
+ float minRefreshRate;
+ float maxRefreshRate;
+
+ status_t result = getDesiredDisplayConfigSpecs(displayToken, &defaultModeId,
+ &minRefreshRate, &maxRefreshRate);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: "
+ "%d",
+ result);
+ return result;
+ }
+
+ result = reply->writeInt32(defaultModeId);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultModeId: %d", result);
+ return result;
+ }
+ result = reply->writeFloat(minRefreshRate);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write minRefreshRate: %d", result);
+ return result;
+ }
+ result = reply->writeFloat(maxRefreshRate);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write maxRefreshRate: %d", result);
+ return result;
+ }
+ reply->writeInt32(result);
+ return result;
+ }
case GET_DISPLAY_BRIGHTNESS_SUPPORT: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> displayToken;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 63eb0c7..9d7d7d0 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1627,6 +1627,16 @@
maxRefreshRate);
}
+status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultModeId,
+ float* outMinRefreshRate,
+ float* outMaxRefreshRate) {
+ return ComposerService::getComposerService()->getDesiredDisplayConfigSpecs(displayToken,
+ outDefaultModeId,
+ outMinRefreshRate,
+ outMaxRefreshRate);
+}
+
status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
Vector<ColorMode>* outColorModes) {
return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index d0ba233..345425d 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -409,6 +409,10 @@
int32_t defaultModeId, float minRefreshRate,
float maxRefreshRate) = 0;
+ virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultModeId,
+ float* outMinRefreshRate,
+ float* outMaxRefreshRate) = 0;
/*
* Gets whether brightness operations are supported on a display.
*
@@ -522,6 +526,7 @@
SET_ALLOWED_DISPLAY_CONFIGS,
GET_ALLOWED_DISPLAY_CONFIGS,
SET_DESIRED_DISPLAY_CONFIG_SPECS,
+ GET_DESIRED_DISPLAY_CONFIG_SPECS,
GET_DISPLAY_BRIGHTNESS_SUPPORT,
SET_DISPLAY_BRIGHTNESS,
CAPTURE_SCREEN_BY_ID,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 273d7bc..2c0b143 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -135,6 +135,15 @@
static status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t defaultModeId, float minRefreshRate,
float maxRefreshRate);
+ // Gets the refresh rate boundaries for display configuration.
+ // For all other parameters, default configuration is used. The index for the default is
+ // corresponting to the configs returned from getDisplayConfigs().
+ // The reason is passed in for telemetry tracking, and it corresponds to the list of all
+ // the policy rules that were used.
+ static status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultModeId,
+ float* outMinRefreshRate,
+ float* outMaxRefreshRate);
// Gets the list of supported color modes for the given display
static status_t getDisplayColorModes(const sp<IBinder>& display,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index c3e4cb9..3d90369 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -836,6 +836,12 @@
float /*maxRefreshRate*/) override {
return NO_ERROR;
}
+ status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/,
+ int32_t* /*outDefaultModeId*/,
+ float* /*outMinRefreshRate*/,
+ float* /*outMaxRefreshRate*/) override {
+ return NO_ERROR;
+ };
status_t notifyPowerHint(int32_t /*hintId*/) override { return NO_ERROR; }
status_t setGlobalShadowSettings(const half4& /*ambientColor*/, const half4& /*spotColor*/,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0a2e071..3a0a86c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3967,6 +3967,12 @@
StringAppendF(&result, "%" PRIu32 " Hz, ",
mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps);
}
+ StringAppendF(&result,
+ "DesiredDisplayConfigSpecs: default config ID: %" PRIu32
+ ", min: %.2f Hz, max: %.2f Hz",
+ mDesiredDisplayConfigSpecs.defaultModeId,
+ mDesiredDisplayConfigSpecs.minRefreshRate,
+ mDesiredDisplayConfigSpecs.maxRefreshRate);
StringAppendF(&result, "(config override by backdoor: %s)\n\n",
mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
@@ -4397,6 +4403,7 @@
case SET_ALLOWED_DISPLAY_CONFIGS:
case GET_ALLOWED_DISPLAY_CONFIGS:
case SET_DESIRED_DISPLAY_CONFIG_SPECS:
+ case GET_DESIRED_DISPLAY_CONFIG_SPECS:
case SET_ACTIVE_COLOR_MODE:
case INJECT_VSYNC:
case SET_POWER_MODE:
@@ -5500,10 +5507,53 @@
return BAD_VALUE;
}
- ALOGD("setDesiredDisplayConfigSpecs: defaultId: %d min: %.f max: %.f", defaultModeId,
- minRefreshRate, maxRefreshRate);
- // TODO(b/142507213): In order to minimize the changelist size, this is going to be implemented
- // in the follow up CL.
+ postMessageSync(new LambdaMessage([&]() {
+ const auto display = getDisplayDeviceLocked(displayToken);
+ if (!display) {
+ ALOGE("Attempt to set desired display configs for invalid display token %p",
+ displayToken.get());
+ } else if (display->isVirtual()) {
+ ALOGW("Attempt to set desired display configs for virtual display");
+ } else {
+ // TODO(b/142507213): Plug through to HWC once the interface is ready.
+ Mutex::Autolock lock(mStateLock);
+ const DesiredDisplayConfigSpecs desiredDisplayConfigSpecs = {defaultModeId,
+ minRefreshRate,
+ maxRefreshRate};
+ if (desiredDisplayConfigSpecs == mDesiredDisplayConfigSpecs) {
+ return;
+ }
+ ALOGV("Updating desired display configs");
+ ALOGD("desiredDisplayConfigSpecs: defaultId: %d min: %.f max: %.f decisions: ",
+ desiredDisplayConfigSpecs.defaultModeId, desiredDisplayConfigSpecs.minRefreshRate,
+ desiredDisplayConfigSpecs.maxRefreshRate);
+ mDesiredDisplayConfigSpecs = desiredDisplayConfigSpecs;
+ }
+ }));
+ return NO_ERROR;
+}
+
+status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultModeId,
+ float* outMinRefreshRate,
+ float* outMaxRefreshRate) {
+ ATRACE_CALL();
+
+ if (!displayToken || !outDefaultModeId || !outMinRefreshRate || !outMaxRefreshRate) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mStateLock);
+ const auto display = getDisplayDeviceLocked(displayToken);
+ if (!display) {
+ return NAME_NOT_FOUND;
+ }
+
+ if (display->isPrimary()) {
+ *outDefaultModeId = mDesiredDisplayConfigSpecs.defaultModeId;
+ *outMinRefreshRate = mDesiredDisplayConfigSpecs.minRefreshRate;
+ *outMaxRefreshRate = mDesiredDisplayConfigSpecs.maxRefreshRate;
+ }
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index caeb022..5f1580b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -386,6 +386,17 @@
void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
};
+ struct DesiredDisplayConfigSpecs {
+ int32_t defaultModeId;
+ float minRefreshRate;
+ float maxRefreshRate;
+
+ bool operator==(const DesiredDisplayConfigSpecs& other) const {
+ return defaultModeId == other.defaultModeId && minRefreshRate == other.minRefreshRate &&
+ maxRefreshRate == other.maxRefreshRate;
+ }
+ };
+
/* ------------------------------------------------------------------------
* IBinder interface
*/
@@ -475,6 +486,9 @@
std::vector<int32_t>* outAllowedConfigs) override;
status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t displayModeId,
float minRefreshRate, float maxRefreshRate) override;
+ status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
+ int32_t* outDefaultModeId, float* outMinRefreshRate,
+ float* outMaxRefreshRate) override;
status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
bool* outSupport) const override;
status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) const override;
@@ -1124,6 +1138,7 @@
// All configs are allowed if the set is empty.
using DisplayConfigs = std::set<int32_t>;
DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock);
+ DesiredDisplayConfigSpecs mDesiredDisplayConfigSpecs GUARDED_BY(mStateLock);
std::mutex mActiveConfigLock;
// This bit is set once we start setting the config. We read from this bit during the
diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
index d752205..420fb29 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -31,10 +31,42 @@
void SetUp() override { mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); }
sp<IBinder> mDisplayToken;
+ int32_t defaultConfigId;
+ float minRefreshRate;
+ float maxRefreshRate;
};
-TEST_F(RefreshRateRangeTest, helloWorldTest) {
- status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 0, 0, 0);
+TEST_F(RefreshRateRangeTest, simpleSetAndGet) {
+ status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 1, 45, 75);
EXPECT_EQ(res, NO_ERROR);
+
+ res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfigId,
+ &minRefreshRate, &maxRefreshRate);
+ EXPECT_EQ(res, NO_ERROR);
+ EXPECT_EQ(defaultConfigId, 1);
+ EXPECT_EQ(minRefreshRate, 45);
+ EXPECT_EQ(maxRefreshRate, 75);
+}
+
+TEST_F(RefreshRateRangeTest, complexSetAndGet) {
+ status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 1, 45, 75);
+ EXPECT_EQ(res, NO_ERROR);
+
+ res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfigId,
+ &minRefreshRate, &maxRefreshRate);
+ EXPECT_EQ(res, NO_ERROR);
+ EXPECT_EQ(defaultConfigId, 1);
+ EXPECT_EQ(minRefreshRate, 45);
+ EXPECT_EQ(maxRefreshRate, 75);
+
+ // Second call overrides the first one.
+ res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 10, 145, 875);
+ EXPECT_EQ(res, NO_ERROR);
+ res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfigId,
+ &minRefreshRate, &maxRefreshRate);
+ EXPECT_EQ(res, NO_ERROR);
+ EXPECT_EQ(defaultConfigId, 10);
+ EXPECT_EQ(minRefreshRate, 145);
+ EXPECT_EQ(maxRefreshRate, 875);
}
} // namespace android