Merge "Rename the newly added maps variable to be more descriptive" into main
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index ba0a38a..a8d12a1 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -39,6 +39,7 @@
std::string calling_package;
int32_t user_id = -1;
bool keep_bugreport_on_retrieval = false;
+ bool skip_user_consent = false;
};
static binder::Status exception(uint32_t code, const std::string& msg,
@@ -62,7 +63,8 @@
[[noreturn]] static void* dumpstate_thread_retrieve(void* data) {
std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data));
- ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package, ds_info->keep_bugreport_on_retrieval);
+ ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package,
+ ds_info->keep_bugreport_on_retrieval, ds_info->skip_user_consent);
MYLOGD("Finished retrieving a bugreport. Exiting.\n");
exit(0);
}
@@ -116,7 +118,8 @@
int bugreport_mode,
int bugreport_flags,
const sp<IDumpstateListener>& listener,
- bool is_screenshot_requested) {
+ bool is_screenshot_requested,
+ bool skip_user_consent) {
MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
// Ensure there is only one bugreport in progress at a time.
@@ -151,7 +154,7 @@
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_flags,
- bugreport_fd, screenshot_fd, is_screenshot_requested);
+ bugreport_fd, screenshot_fd, is_screenshot_requested, skip_user_consent);
if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) {
MYLOGE("Invalid filedescriptor");
@@ -207,6 +210,7 @@
android::base::unique_fd bugreport_fd,
const std::string& bugreport_file,
const bool keep_bugreport_on_retrieval,
+ const bool skip_user_consent,
const sp<IDumpstateListener>& listener) {
ds_ = &(Dumpstate::GetInstance());
@@ -216,6 +220,7 @@
ds_info->calling_package = calling_package;
ds_info->user_id = user_id;
ds_info->keep_bugreport_on_retrieval = keep_bugreport_on_retrieval;
+ ds_info->skip_user_consent = skip_user_consent;
ds_->listener_ = listener;
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
// Use a /dev/null FD when initializing options since none is provided.
@@ -223,7 +228,7 @@
TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
options->Initialize(Dumpstate::BugreportMode::BUGREPORT_DEFAULT,
- 0, bugreport_fd, devnull_fd, false);
+ 0, bugreport_fd, devnull_fd, false, skip_user_consent);
if (bugreport_fd.get() == -1) {
MYLOGE("Invalid filedescriptor");
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 7b76c36..c99f70e 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -44,7 +44,7 @@
android::base::unique_fd bugreport_fd,
android::base::unique_fd screenshot_fd, int bugreport_mode,
int bugreport_flags, const sp<IDumpstateListener>& listener,
- bool is_screenshot_requested) override;
+ bool is_screenshot_requested, bool skip_user_consent) override;
binder::Status retrieveBugreport(int32_t calling_uid,
const std::string& calling_package,
@@ -52,6 +52,7 @@
android::base::unique_fd bugreport_fd,
const std::string& bugreport_file,
const bool keep_bugreport_on_retrieval,
+ const bool skip_user_consent,
const sp<IDumpstateListener>& listener)
override;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 97c470e..3b8fde9 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -96,7 +96,8 @@
void startBugreport(int callingUid, @utf8InCpp String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, int bugreportFlags,
- IDumpstateListener listener, boolean isScreenshotRequested);
+ IDumpstateListener listener, boolean isScreenshotRequested,
+ boolean skipUserConsent);
/**
* Cancels the bugreport currently in progress.
@@ -130,5 +131,6 @@
FileDescriptor bugreportFd,
@utf8InCpp String bugreportFile,
boolean keepBugreportOnRetrieval,
+ boolean skipUserConsent,
IDumpstateListener listener);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 6b9a0a0..d5125f0 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2902,9 +2902,11 @@
int bugreport_flags,
const android::base::unique_fd& bugreport_fd_in,
const android::base::unique_fd& screenshot_fd_in,
- bool is_screenshot_requested) {
+ bool is_screenshot_requested,
+ bool skip_user_consent) {
this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA;
this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
+ this->skip_user_consent = skip_user_consent;
// Duplicate the fds because the passed in fds don't outlive the binder transaction.
bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
@@ -2992,46 +2994,52 @@
}
Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package,
- const bool keep_bugreport_on_retrieval) {
+ const bool keep_bugreport_on_retrieval,
+ const bool skip_user_consent) {
Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package,
- keep_bugreport_on_retrieval);
+ keep_bugreport_on_retrieval,
+ skip_user_consent);
HandleRunStatus(status);
return status;
}
Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid,
const std::string& calling_package,
- const bool keep_bugreport_on_retrieval) {
- consent_callback_ = new ConsentCallback();
- const String16 incidentcompanion("incidentcompanion");
- sp<android::IBinder> ics(
- defaultServiceManager()->checkService(incidentcompanion));
- android::String16 package(calling_package.c_str());
- if (ics != nullptr) {
- MYLOGD("Checking user consent via incidentcompanion service\n");
- android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
- calling_uid, package, String16(), String16(),
- 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
- } else {
- MYLOGD(
- "Unable to check user consent; incidentcompanion service unavailable\n");
- return RunStatus::USER_CONSENT_TIMED_OUT;
- }
- UserConsentResult consent_result = consent_callback_->getResult();
- int timeout_ms = 30 * 1000;
- while (consent_result == UserConsentResult::UNAVAILABLE &&
- consent_callback_->getElapsedTimeMs() < timeout_ms) {
- sleep(1);
- consent_result = consent_callback_->getResult();
- }
- if (consent_result == UserConsentResult::DENIED) {
- return RunStatus::USER_CONSENT_DENIED;
- }
- if (consent_result == UserConsentResult::UNAVAILABLE) {
- MYLOGD("Canceling user consent request via incidentcompanion service\n");
- android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
- consent_callback_.get());
- return RunStatus::USER_CONSENT_TIMED_OUT;
+ const bool keep_bugreport_on_retrieval,
+ const bool skip_user_consent) {
+ if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) {
+ consent_callback_ = new ConsentCallback();
+ const String16 incidentcompanion("incidentcompanion");
+ sp<android::IBinder> ics(
+ defaultServiceManager()->checkService(incidentcompanion));
+ android::String16 package(calling_package.c_str());
+ if (ics != nullptr) {
+ MYLOGD("Checking user consent via incidentcompanion service\n");
+
+ android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
+ calling_uid, package, String16(), String16(),
+ 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
+ } else {
+ MYLOGD(
+ "Unable to check user consent; incidentcompanion service unavailable\n");
+ return RunStatus::USER_CONSENT_TIMED_OUT;
+ }
+ UserConsentResult consent_result = consent_callback_->getResult();
+ int timeout_ms = 30 * 1000;
+ while (consent_result == UserConsentResult::UNAVAILABLE &&
+ consent_callback_->getElapsedTimeMs() < timeout_ms) {
+ sleep(1);
+ consent_result = consent_callback_->getResult();
+ }
+ if (consent_result == UserConsentResult::DENIED) {
+ return RunStatus::USER_CONSENT_DENIED;
+ }
+ if (consent_result == UserConsentResult::UNAVAILABLE) {
+ MYLOGD("Canceling user consent request via incidentcompanion service\n");
+ android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
+ consent_callback_.get());
+ return RunStatus::USER_CONSENT_TIMED_OUT;
+ }
}
bool copy_succeeded =
@@ -3510,7 +3518,9 @@
void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
if (multiuser_get_app_id(calling_uid) == AID_SHELL ||
- !CalledByApi() || options_->is_consent_deferred) {
+ !CalledByApi() || options_->is_consent_deferred ||
+ (android::app::admin::flags::onboarding_consentless_bugreports() &&
+ options_->skip_user_consent)) {
// No need to get consent for shell triggered dumpstates, or not
// through bugreporting API (i.e. no fd to copy back), or when consent
// is deferred.
@@ -3596,7 +3606,8 @@
// If the caller has asked to copy the bugreport over to their directory, we need explicit
// user consent (unless the caller is Shell).
UserConsentResult consent_result;
- if (multiuser_get_app_id(calling_uid) == AID_SHELL) {
+ if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent
+ && android::app::admin::flags::onboarding_consentless_bugreports())) {
consent_result = UserConsentResult::APPROVED;
} else {
consent_result = consent_callback_->getResult();
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 46d949e..fcb8cf3 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -364,7 +364,7 @@
* Initialize() dumpstate before calling this method.
*/
RunStatus Retrieve(int32_t calling_uid, const std::string& calling_package,
- const bool keep_bugreport_on_retrieval);
+ const bool keep_bugreport_on_retrieval, const bool skip_user_consent);
@@ -412,6 +412,7 @@
bool do_screenshot = false;
bool is_screenshot_copied = false;
bool is_consent_deferred = false;
+ bool skip_user_consent = false;
bool is_remote_mode = false;
bool show_header_only = false;
bool telephony_only = false;
@@ -448,7 +449,8 @@
void Initialize(BugreportMode bugreport_mode, int bugreport_flags,
const android::base::unique_fd& bugreport_fd,
const android::base::unique_fd& screenshot_fd,
- bool is_screenshot_requested);
+ bool is_screenshot_requested,
+ bool skip_user_consent);
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
@@ -564,7 +566,8 @@
private:
RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package);
RunStatus RetrieveInternal(int32_t calling_uid, const std::string& calling_package,
- const bool keep_bugreport_on_retrieval);
+ const bool keep_bugreport_on_retrieval,
+ const bool skip_user_consent);
RunStatus DumpstateDefaultAfterCritical();
RunStatus dumpstate();
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index ccf64fe..a29923a 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -507,7 +507,7 @@
ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd),
std::move(screenshot_fd),
Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, listener,
- true);
+ true, false);
// startBugreport is an async call. Verify binder call succeeded first, then wait till listener
// gets expected callbacks.
EXPECT_TRUE(status.isOk());
@@ -545,7 +545,7 @@
android::binder::Status status =
ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd),
std::move(screenshot_fd), 2000, // invalid bugreport mode
- flags, listener, false);
+ flags, listener, false, false);
EXPECT_EQ(listener->getErrorCode(), IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
// The service should have died, freeing itself up for a new invocation.
@@ -579,7 +579,7 @@
ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd),
std::move(screenshot_fd),
Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, listener1,
- true);
+ true, false);
EXPECT_TRUE(status.isOk());
// try to make another call to startBugreport. This should fail.
@@ -587,7 +587,7 @@
status = ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd2),
std::move(screenshot_fd2),
Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags,
- listener2, true);
+ listener2, true, false);
EXPECT_FALSE(status.isOk());
WaitTillExecutionComplete(listener2.get());
EXPECT_EQ(listener2->getErrorCode(),
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2afabed..18c2f94 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -239,7 +239,7 @@
}
TEST_F(DumpOptionsTest, InitializeFullBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true, false);
EXPECT_TRUE(options_.do_screenshot);
// Other options retain default values
@@ -253,7 +253,7 @@
}
TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true, false);
EXPECT_TRUE(options_.do_progress_updates);
EXPECT_TRUE(options_.do_screenshot);
@@ -267,7 +267,7 @@
}
TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false, false);
EXPECT_TRUE(options_.is_remote_mode);
EXPECT_FALSE(options_.do_vibrate);
EXPECT_FALSE(options_.do_screenshot);
@@ -281,7 +281,7 @@
}
TEST_F(DumpOptionsTest, InitializeWearBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true, false);
EXPECT_TRUE(options_.do_screenshot);
EXPECT_TRUE(options_.do_progress_updates);
@@ -296,7 +296,7 @@
}
TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false, false);
EXPECT_FALSE(options_.do_screenshot);
EXPECT_TRUE(options_.telephony_only);
EXPECT_TRUE(options_.do_progress_updates);
@@ -311,7 +311,7 @@
}
TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false, false);
EXPECT_FALSE(options_.do_screenshot);
EXPECT_TRUE(options_.wifi_only);
@@ -491,12 +491,12 @@
int flags = Dumpstate::BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA |
Dumpstate::BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
options_.Initialize(
- Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true);
+ Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true, false);
EXPECT_TRUE(options_.is_consent_deferred);
EXPECT_TRUE(options_.use_predumped_ui_data);
options_.Initialize(
- Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
+ Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true, false);
EXPECT_FALSE(options_.is_consent_deferred);
EXPECT_FALSE(options_.use_predumped_ui_data);
}
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
index 9cf62bc..7ee291d 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -74,6 +74,7 @@
} // namespace android::gui
using android::gui::METADATA_ACCESSIBILITY_ID;
+using android::gui::METADATA_CALLING_UID;
using android::gui::METADATA_DEQUEUE_TIME;
using android::gui::METADATA_GAME_MODE;
using android::gui::METADATA_MOUSE_CURSOR;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 325a911..b973211 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -91,7 +91,6 @@
// Debugging settings
static const bool kPrintLayerSettings = false;
static const bool kGaneshFlushAfterEveryLayer = kPrintLayerSettings;
-static constexpr bool kEnableLayerBrightening = true;
} // namespace
@@ -714,8 +713,7 @@
// ...and compute the dimming ratio if dimming is requested
const float displayDimmingRatio = display.targetLuminanceNits > 0.f &&
- maxLayerWhitePoint > 0.f &&
- (kEnableLayerBrightening || display.targetLuminanceNits > maxLayerWhitePoint)
+ maxLayerWhitePoint > 0.f && display.targetLuminanceNits > maxLayerWhitePoint
? maxLayerWhitePoint / display.targetLuminanceNits
: 1.f;
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 795f088..889ee09 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -310,9 +310,6 @@
/* Called by the heartbeat to ensures that the reader has not deadlocked. */
virtual void monitor() = 0;
- /* Returns true if the input device is enabled. */
- virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
-
/* Makes the reader start processing events from the kernel. */
virtual status_t start() = 0;
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 69555f8..b9523ef 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -874,17 +874,6 @@
return std::nullopt;
}
-bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
- std::scoped_lock _l(mLock);
-
- InputDevice* device = findInputDeviceLocked(deviceId);
- if (device) {
- return device->isEnabled();
- }
- ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
- return false;
-}
-
bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) {
std::scoped_lock _l(mLock);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 92a778a..7e701c5 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -61,8 +61,6 @@
std::vector<InputDeviceInfo> getInputDevices() const override;
- bool isInputDeviceEnabled(int32_t deviceId) override;
-
int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) override;
int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) override;
int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) override;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 8ad235f..8de28c6 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -7814,6 +7814,7 @@
* If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
*/
TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
+ SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> leftWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index a19726a..7d26a43 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -55,8 +55,6 @@
void monitor() { reader->monitor(); }
- bool isInputDeviceEnabled(int32_t deviceId) { return reader->isInputDeviceEnabled(deviceId); }
-
status_t start() { return reader->start(); }
status_t stop() { return reader->stop(); }
@@ -206,7 +204,6 @@
},
[&]() -> void { reader->monitor(); },
[&]() -> void { reader->getInputDevices(); },
- [&]() -> void { reader->isInputDeviceEnabled(fdp->ConsumeIntegral<int32_t>()); },
[&]() -> void {
reader->getScanCodeState(fdp->ConsumeIntegral<int32_t>(),
fdp->ConsumeIntegral<uint32_t>(),
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index f62562c..9c4d1ac 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -429,14 +429,18 @@
}
void SensorDevice::onDynamicSensorsDisconnected(
- const std::vector<int32_t>& dynamicSensorHandlesRemoved) {
- if (sensorservice_flags::sensor_device_on_dynamic_sensor_disconnected()) {
- for (auto handle : dynamicSensorHandlesRemoved) {
- auto it = mConnectedDynamicSensors.find(handle);
- if (it != mConnectedDynamicSensors.end()) {
- mConnectedDynamicSensors.erase(it);
- }
- }
+ const std::vector<int32_t>& /*dynamicSensorHandlesRemoved*/) {
+ // This function is currently a no-op has removing data in mConnectedDynamicSensors here will
+ // cause a race condition between when this callback is invoked and when the dynamic sensor meta
+ // event is processed by polling. The clean up should only happen after processing the meta
+ // event. See the call stack of cleanupDisconnectedDynamicSensor.
+}
+
+void SensorDevice::cleanupDisconnectedDynamicSensor(int handle) {
+ std::lock_guard<std::mutex> lock(mDynamicSensorsMutex);
+ auto it = mConnectedDynamicSensors.find(handle);
+ if (it != mConnectedDynamicSensors.end()) {
+ mConnectedDynamicSensors.erase(it);
}
}
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 52f7cf2..b7b04b5 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -63,6 +63,14 @@
std::vector<int32_t> getDynamicSensorHandles();
void handleDynamicSensorConnection(int handle, bool connected);
+ /**
+ * Removes handle from connected dynamic sensor list. Note that this method must be called after
+ * SensorService has done using sensor data.
+ *
+ * @param handle of the disconnected dynamic sensor.
+ */
+ void cleanupDisconnectedDynamicSensor(int handle);
+
status_t initCheck() const;
int getHalDeviceVersion() const;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 69e4309..70ca702 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1273,6 +1273,7 @@
} else {
int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
disconnectDynamicSensor(handle, activeConnections);
+ device.cleanupDisconnectedDynamicSensor(handle);
}
}
}
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index d0e2d7a..c9ed157 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -543,12 +543,14 @@
}
void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
- Fps displayFrameRenderRate, nsecs_t& deadlineDelta) {
+ Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) {
if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
// Cannot do any classification for invalid present time.
mJankType = JankType::Unknown;
mJankSeverityType = JankSeverityType::Unknown;
- deadlineDelta = -1;
+ if (outDeadlineDelta) {
+ *outDeadlineDelta = -1;
+ }
return;
}
@@ -559,7 +561,9 @@
mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
: JankType::AppDeadlineMissed;
mJankSeverityType = JankSeverityType::Unknown;
- deadlineDelta = -1;
+ if (outDeadlineDelta) {
+ *outDeadlineDelta = -1;
+ }
return;
}
@@ -568,11 +572,14 @@
return;
}
- deadlineDelta = mActuals.endTime - mPredictions.endTime;
const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
: 0;
+ const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
+ if (outDeadlineDelta) {
+ *outDeadlineDelta = deadlineDelta;
+ }
if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
@@ -671,7 +678,7 @@
mActuals.presentTime = presentTime;
nsecs_t deadlineDelta = 0;
- classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, deadlineDelta);
+ classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, &deadlineDelta);
if (mPredictionState != PredictionState::None) {
// Only update janky frames if the app used vsync predictions
@@ -681,6 +688,14 @@
}
}
+void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate) {
+ std::scoped_lock lock(mMutex);
+
+ mDisplayFrameRenderRate = displayFrameRenderRate;
+ mActuals.presentTime = mPredictions.presentTime;
+ classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
+}
+
void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
@@ -912,6 +927,15 @@
finalizeCurrentDisplayFrame();
}
+void FrameTimeline::onCommitNotComposited() {
+ ATRACE_CALL();
+ std::scoped_lock lock(mMutex);
+ mCurrentDisplayFrame->onCommitNotComposited();
+ mCurrentDisplayFrame.reset();
+ mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
+ &mTraceCookieCounter);
+}
+
void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
mSurfaceFrames.push_back(surfaceFrame);
}
@@ -1094,6 +1118,12 @@
}
}
+void FrameTimeline::DisplayFrame::onCommitNotComposited() {
+ for (auto& surfaceFrame : mSurfaceFrames) {
+ surfaceFrame->onCommitNotComposited(mRefreshRate, mRenderRate);
+ }
+}
+
void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
nsecs_t monoBootOffset) const {
int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index a76f7d4..94cfcb4 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -204,6 +204,8 @@
void onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
nsecs_t displayPresentDelta);
+ // Sets the frame as none janky as there was no real display frame.
+ void onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate);
// All the timestamps are dumped relative to the baseTime
void dump(std::string& result, const std::string& indent, nsecs_t baseTime) const;
// Dumps only the layer, token, is buffer, jank metadata, prediction and present states.
@@ -235,7 +237,7 @@
void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
- Fps displayFrameRenderRate, nsecs_t& deadlineDelta) REQUIRES(mMutex);
+ Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) REQUIRES(mMutex);
const int64_t mToken;
const int32_t mInputEventId;
@@ -318,6 +320,10 @@
virtual void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
const std::shared_ptr<FenceTime>& gpuFence) = 0;
+ // Tells FrameTimeline that a frame was committed but not composited. This is used to flush
+ // all the associated surface frames.
+ virtual void onCommitNotComposited() = 0;
+
// Args:
// -jank : Dumps only the Display Frames that are either janky themselves
// or contain janky Surface Frames.
@@ -390,6 +396,8 @@
std::optional<TimelineItem> predictions, nsecs_t wakeUpTime);
// Sets the appropriate metadata and classifies the jank.
void onPresent(nsecs_t signalTime, nsecs_t previousPresentTime);
+ // Flushes all the surface frames as those were not generating any actual display frames.
+ void onCommitNotComposited();
// Adds the provided SurfaceFrame to the current display frame.
void addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame);
@@ -475,6 +483,7 @@
void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate, Fps renderRate) override;
void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
const std::shared_ptr<FenceTime>& gpuFence = FenceTime::NO_FENCE) override;
+ void onCommitNotComposited() override;
void parseArgs(const Vector<String16>& args, std::string& result) override;
void setMaxDisplayFrames(uint32_t size) override;
float computeFps(const std::unordered_set<int32_t>& layerIds) override;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index f2497d4..f10bb33 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -313,6 +313,21 @@
}
}
+void updateMetadataAndGameMode(LayerSnapshot& snapshot, const RequestedLayerState& requested,
+ const LayerSnapshotBuilder::Args& args,
+ const LayerSnapshot& parentSnapshot) {
+ if (snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
+ snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
+ ? requested.gameMode
+ : parentSnapshot.gameMode;
+ }
+ updateMetadata(snapshot, requested, args);
+ if (args.includeMetadata) {
+ snapshot.layerMetadata = parentSnapshot.layerMetadata;
+ snapshot.layerMetadata.merge(requested.metadata);
+ }
+}
+
void clearChanges(LayerSnapshot& snapshot) {
snapshot.changes.clear();
snapshot.clientChanges = 0;
@@ -746,6 +761,11 @@
RequestedLayerState::Changes::Input)) {
updateInput(snapshot, requested, parentSnapshot, path, args);
}
+ if (forceUpdate ||
+ (args.includeMetadata &&
+ snapshot.changes.test(RequestedLayerState::Changes::Metadata))) {
+ updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
+ }
return;
}
@@ -785,15 +805,8 @@
}
}
- if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
- snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
- ? requested.gameMode
- : parentSnapshot.gameMode;
- updateMetadata(snapshot, requested, args);
- if (args.includeMetadata) {
- snapshot.layerMetadata = parentSnapshot.layerMetadata;
- snapshot.layerMetadata.merge(requested.metadata);
- }
+ if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::Metadata)) {
+ updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot);
}
if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
@@ -1162,6 +1175,15 @@
}
}
+void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor,
+ const ConstPredicate& predicate) {
+ for (int i = 0; i < mNumInterestingSnapshots; i++) {
+ std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
+ if (!predicate(*snapshot)) continue;
+ visitor(snapshot);
+ }
+}
+
void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 1cec018..dbbad76 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -86,6 +86,11 @@
// Visit each visible snapshot in z-order and move the snapshot if needed
void forEachVisibleSnapshot(const Visitor& visitor);
+ typedef std::function<bool(const LayerSnapshot& snapshot)> ConstPredicate;
+ // Visit each snapshot that satisfies the predicate and move the snapshot if needed with visible
+ // snapshots in z-order
+ void forEachSnapshot(const Visitor& visitor, const ConstPredicate& predicate);
+
// Visit each snapshot interesting to input reverse z-order
void forEachInputSnapshot(const ConstVisitor& visitor) const;
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 028bd19..5631fac 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -328,6 +328,7 @@
changes |= RequestedLayerState::Changes::GameMode;
}
}
+ changes |= RequestedLayerState::Changes::Metadata;
}
if (clientState.what & layer_state_t::eFrameRateChanged) {
const auto compatibility =
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 09f33de..48b9640 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -26,6 +26,7 @@
#include "TransactionState.h"
namespace android::surfaceflinger::frontend {
+using namespace ftl::flag_operators;
// Stores client requested states for a layer.
// This struct does not store any other states or states pertaining to
@@ -58,6 +59,13 @@
GameMode = 1u << 19,
BufferUsageFlags = 1u << 20,
};
+
+ static constexpr ftl::Flags<Changes> kMustComposite = Changes::Created | Changes::Destroyed |
+ Changes::Hierarchy | Changes::Geometry | Changes::Content | Changes::Input |
+ Changes::Z | Changes::Mirror | Changes::Parent | Changes::RelativeParent |
+ Changes::Metadata | Changes::Visibility | Changes::VisibleRegion | Changes::Buffer |
+ Changes::SidebandStream | Changes::Animation | Changes::BufferSize | Changes::GameMode |
+ Changes::BufferUsageFlags;
static Rect reduce(const Rect& win, const Region& exclude);
RequestedLayerState(const LayerCreationArgs&);
void merge(const ResolvedComposerState&);
diff --git a/services/surfaceflinger/Scheduler/ISchedulerCallback.h b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
index 9f4f5b6..43cdb5e 100644
--- a/services/surfaceflinger/Scheduler/ISchedulerCallback.h
+++ b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
@@ -32,6 +32,7 @@
virtual void onChoreographerAttached() = 0;
virtual void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>,
Fps renderRate) = 0;
+ virtual void onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) = 0;
protected:
~ISchedulerCallback() = default;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index a37fb96..2c66492 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -1590,7 +1590,8 @@
std::lock_guard lock(mLock);
const auto activeMode = getActiveModeLocked();
- dumper.dump("activeMode"sv, to_string(activeMode));
+ dumper.dump("renderRate"sv, to_string(activeMode.fps));
+ dumper.dump("activeMode"sv, to_string(*activeMode.modePtr));
dumper.dump("displayModes"sv);
{
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 005ec05..60681a2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -221,6 +221,7 @@
if (FlagManager::getInstance().vrr_config()) {
compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
}
+ mSchedulerCallback.onCommitNotComposited(pacesetterPtr->displayId);
return;
}
}
@@ -1152,8 +1153,10 @@
return pacesetterFps;
}();
+ // Choose a mode for powered-on follower displays.
for (const auto& [id, display] : mDisplays) {
if (id == *mPacesetterDisplayId) continue;
+ if (display.powerMode != hal::PowerMode::ON) continue;
auto rankedFrameRates =
display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals,
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 0b47924..85ce713 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -650,29 +650,33 @@
const auto threshold = model.slope / 2;
const auto lastFrameMissed =
lastVsyncOpt && std::abs(*lastVsyncOpt - missedVsync.vsync.ns()) < threshold;
- if (FlagManager::getInstance().vrr_config() && lastFrameMissed) {
- // If the last frame missed is the last vsync, we already shifted the timeline. Depends on
- // whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a different
- // fixup. There is no need to to shift the vsync timeline again.
- vsyncTime += missedVsync.fixup.ns();
- ATRACE_FORMAT_INSTANT("lastFrameMissed");
- } else if (FlagManager::getInstance().vrr_config() && minFramePeriodOpt && mRenderRateOpt &&
- lastVsyncOpt) {
- // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it
- // first before trying to use it.
- lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt);
- const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
- if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) {
- // avoid a duplicate vsync
- ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f which "
- "is %.2f "
- "from "
- "prev. "
- "adjust by %.2f",
- static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
- static_cast<float>(vsyncDiff) / 1e6f,
- static_cast<float>(mRenderRateOpt->getPeriodNsecs()) / 1e6f);
- vsyncTime += mRenderRateOpt->getPeriodNsecs();
+ const auto mightBackpressure = minFramePeriodOpt && mRenderRateOpt &&
+ mRenderRateOpt->getPeriod() < 2 * (*minFramePeriodOpt);
+ if (FlagManager::getInstance().vrr_config()) {
+ if (lastFrameMissed) {
+ // If the last frame missed is the last vsync, we already shifted the timeline. Depends
+ // on whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a
+ // different fixup. There is no need to to shift the vsync timeline again.
+ vsyncTime += missedVsync.fixup.ns();
+ ATRACE_FORMAT_INSTANT("lastFrameMissed");
+ } else if (mightBackpressure && lastVsyncOpt) {
+ // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it
+ // first before trying to use it.
+ lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt);
+ const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
+ if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) {
+ // avoid a duplicate vsync
+ ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f "
+ "which "
+ "is %.2f "
+ "from "
+ "prev. "
+ "adjust by %.2f",
+ static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
+ static_cast<float>(vsyncDiff) / 1e6f,
+ static_cast<float>(mRenderRateOpt->getPeriodNsecs()) / 1e6f);
+ vsyncTime += mRenderRateOpt->getPeriodNsecs();
+ }
}
}
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
index 59a6df2..f2be316 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
@@ -36,8 +36,11 @@
};
inline std::string to_string(const FrameRateMode& mode) {
- return to_string(mode.fps) + " (" + to_string(mode.modePtr->getPeakFps()) + "(" +
- to_string(mode.modePtr->getVsyncRate()) + "))";
+ return base::StringPrintf("{fps=%s, modePtr={id=%d, vsyncRate=%s, peakRefreshRate=%s}}",
+ to_string(mode.fps).c_str(),
+ ftl::to_underlying(mode.modePtr->getId()),
+ to_string(mode.modePtr->getVsyncRate()).c_str(),
+ to_string(mode.modePtr->getPeakFps()).c_str());
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5bb279e..cf67f67 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1411,11 +1411,12 @@
}
}
-void SurfaceFlinger::initiateDisplayModeChanges() {
+bool SurfaceFlinger::initiateDisplayModeChanges() {
ATRACE_CALL();
std::optional<PhysicalDisplayId> displayToUpdateImmediately;
+ bool mustComposite = false;
for (const auto& [id, physical] : mPhysicalDisplays) {
const auto display = getDisplayDeviceLocked(id);
if (!display) continue;
@@ -1425,11 +1426,6 @@
continue;
}
- if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
- dropModeRequest(display);
- continue;
- }
-
const auto desiredModeId = desiredModeOpt->mode.modePtr->getId();
const auto displayModePtrOpt = physical.snapshot().displayModes().get(desiredModeId);
@@ -1472,7 +1468,11 @@
mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
if (outTimeline.refreshRequired) {
- scheduleComposite(FrameHint::kNone);
+ if (FlagManager::getInstance().vrr_bugfix_24q4()) {
+ mustComposite = true;
+ } else {
+ scheduleComposite(FrameHint::kNone);
+ }
} else {
// TODO(b/255635711): Remove `displayToUpdateImmediately` to `finalizeDisplayModeChange`
// for all displays. This was only needed when the loop iterated over `mDisplays` rather
@@ -1490,6 +1490,8 @@
applyActiveMode(display);
}
}
+
+ return mustComposite;
}
void SurfaceFlinger::disableExpensiveRendering() {
@@ -2439,7 +2441,12 @@
mUpdateAttachedChoreographer = true;
}
outTransactionsAreEmpty = mLayerLifecycleManager.getGlobalChanges().get() == 0;
- mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
+ if (FlagManager::getInstance().vrr_bugfix_24q4()) {
+ mustComposite |= mLayerLifecycleManager.getGlobalChanges().any(
+ frontend::RequestedLayerState::kMustComposite);
+ } else {
+ mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
+ }
bool newDataLatched = false;
ATRACE_NAME("DisplayCallbackAndStatsUpdates");
@@ -2664,7 +2671,7 @@
? &mLayerHierarchyBuilder.getHierarchy()
: nullptr,
updateAttachedChoreographer);
- initiateDisplayModeChanges();
+ mustComposite |= initiateDisplayModeChanges();
}
updateCursorAsync();
@@ -4228,12 +4235,6 @@
if (!display) continue;
- if (ftl::FakeGuard guard(kMainThreadContext);
- !shouldApplyRefreshRateSelectorPolicy(*display)) {
- ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str());
- continue;
- }
-
if (display->refreshRateSelector().isModeAllowed(request.mode)) {
setDesiredMode(std::move(request));
} else {
@@ -4405,6 +4406,12 @@
scheduleNotifyExpectedPresentHint(displayId);
}
+void SurfaceFlinger::onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) {
+ if (FlagManager::getInstance().commit_not_composited()) {
+ mFrameTimeline->onCommitNotComposited();
+ }
+}
+
void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
using namespace scheduler;
@@ -7501,14 +7508,11 @@
auto future = mScheduler->schedule(
[&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
n = data.readInt32();
- mHdrSdrRatioOverlay = n != 0;
- switch (n) {
- case 0:
- case 1:
- enableHdrSdrRatioOverlay(mHdrSdrRatioOverlay);
- break;
- default:
- reply->writeBool(isHdrSdrRatioOverlayEnabled());
+ if (n == 0 || n == 1) {
+ mHdrSdrRatioOverlay = n != 0;
+ enableHdrSdrRatioOverlay(mHdrSdrRatioOverlay);
+ } else {
+ reply->writeBool(isHdrSdrRatioOverlayEnabled());
}
});
future.wait();
@@ -8328,10 +8332,7 @@
renderArea->getHintForSeamlessTransition());
sdrWhitePointNits = state.sdrWhitePointNits;
- // TODO(b/298219334): Clean this up once we verify this doesn't break anything
- static constexpr bool kScreenshotsDontDim = true;
-
- if (kScreenshotsDontDim && !captureResults.capturedHdrLayers) {
+ if (!captureResults.capturedHdrLayers) {
displayBrightnessNits = sdrWhitePointNits;
} else {
displayBrightnessNits = state.displayBrightnessNits;
@@ -8563,35 +8564,11 @@
break;
}
- if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
- ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str());
- return NO_ERROR;
- }
-
return applyRefreshRateSelectorPolicy(displayId, selector);
}
-bool SurfaceFlinger::shouldApplyRefreshRateSelectorPolicy(const DisplayDevice& display) const {
- if (display.isPoweredOn() || mPhysicalDisplays.size() == 1) return true;
-
- LOG_ALWAYS_FATAL_IF(display.isVirtual());
- const auto displayId = display.getPhysicalId();
-
- // The display is powered off, and this is a multi-display device. If the display is the
- // inactive internal display of a dual-display foldable, then the policy will be applied
- // when it becomes active upon powering on.
- //
- // TODO(b/255635711): Remove this function (i.e. returning `false` as a special case) once
- // concurrent mode setting across multiple (potentially powered off) displays is supported.
- //
- return displayId == mActiveDisplayId ||
- !mPhysicalDisplays.get(displayId)
- .transform(&PhysicalDisplay::isInternal)
- .value_or(false);
-}
-
status_t SurfaceFlinger::applyRefreshRateSelectorPolicy(
- PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector, bool force) {
+ PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector) {
const scheduler::RefreshRateSelector::Policy currentPolicy = selector.getCurrentPolicy();
ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
@@ -8622,7 +8599,7 @@
return INVALID_OPERATION;
}
- setDesiredMode({std::move(preferredMode), .emitEvent = true, .force = force});
+ setDesiredMode({std::move(preferredMode), .emitEvent = true});
// Update the frameRateOverride list as the display render rate might have changed
if (mScheduler->updateFrameRateOverrides(scheduler::GlobalSignals{}, preferredFps)) {
@@ -8980,13 +8957,8 @@
const DisplayDevice& activeDisplay) {
ATRACE_CALL();
- // For the first display activated during boot, there is no need to force setDesiredMode,
- // because DM is about to send its policy via setDesiredDisplayModeSpecs.
- bool forceApplyPolicy = false;
-
if (inactiveDisplayPtr) {
inactiveDisplayPtr->getCompositionDisplay()->setLayerCachingTexturePoolEnabled(false);
- forceApplyPolicy = true;
}
mActiveDisplayId = activeDisplay.getPhysicalId();
@@ -9003,12 +8975,11 @@
mActiveDisplayTransformHint = activeDisplay.getTransformHint();
sActiveDisplayRotationFlags = ui::Transform::toRotationFlags(activeDisplay.getOrientation());
- // The policy of the new active/pacesetter display may have changed while it was inactive. In
- // that case, its preferred mode has not been propagated to HWC (via setDesiredMode). In either
- // case, the Scheduler's cachedModeChangedParams must be initialized to the newly active mode,
- // and the kernel idle timer of the newly active display must be toggled.
- applyRefreshRateSelectorPolicy(mActiveDisplayId, activeDisplay.refreshRateSelector(),
- forceApplyPolicy);
+ // Whether or not the policy of the new active/pacesetter display changed while it was inactive
+ // (in which case its preferred mode has already been propagated to HWC via setDesiredMode), the
+ // Scheduler's cachedModeChangedParams must be initialized to the newly active mode, and the
+ // kernel idle timer of the newly active display must be toggled.
+ applyRefreshRateSelectorPolicy(mActiveDisplayId, activeDisplay.refreshRateSelector());
}
status_t SurfaceFlinger::addWindowInfosListener(const sp<IWindowInfosListener>& windowInfosListener,
@@ -9227,7 +9198,9 @@
std::vector<std::pair<Layer*, LayerFE*>> layers;
if (mLayerLifecycleManagerEnabled) {
nsecs_t currentTime = systemTime();
- mLayerSnapshotBuilder.forEachVisibleSnapshot(
+ const bool needsMetadata = mCompositionEngine->getFeatureFlags().test(
+ compositionengine::Feature::kSnapshotLayerMetadata);
+ mLayerSnapshotBuilder.forEachSnapshot(
[&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD(
kMainThreadContext) {
if (cursorOnly &&
@@ -9250,6 +9223,12 @@
layerFE->mSnapshot = std::move(snapshot);
refreshArgs.layers.push_back(layerFE);
layers.emplace_back(legacyLayer.get(), layerFE.get());
+ },
+ [needsMetadata](const frontend::LayerSnapshot& snapshot) {
+ return snapshot.isVisible ||
+ (needsMetadata &&
+ snapshot.changes.test(
+ frontend::RequestedLayerState::Changes::Metadata));
});
}
if (!mLayerLifecycleManagerEnabled) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8474515..278dee74 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -700,6 +700,8 @@
void onChoreographerAttached() override;
void onExpectedPresentTimePosted(TimePoint expectedPresentTime, ftl::NonNull<DisplayModePtr>,
Fps renderRate) override;
+ void onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) override
+ REQUIRES(kMainThreadContext);
// ICEPowerCallback overrides:
void notifyCpuLoadUp() override;
@@ -734,7 +736,7 @@
status_t setActiveModeFromBackdoor(const sp<display::DisplayToken>&, DisplayModeId, Fps minFps,
Fps maxFps);
- void initiateDisplayModeChanges() REQUIRES(mStateLock, kMainThreadContext);
+ bool initiateDisplayModeChanges() REQUIRES(mStateLock, kMainThreadContext);
void finalizeDisplayModeChange(DisplayDevice&) REQUIRES(mStateLock, kMainThreadContext);
// TODO(b/241285191): Replace DisplayDevice with DisplayModeRequest, and move to Scheduler.
@@ -754,13 +756,9 @@
const sp<DisplayDevice>&, const scheduler::RefreshRateSelector::PolicyVariant&)
EXCLUDES(mStateLock) REQUIRES(kMainThreadContext);
- bool shouldApplyRefreshRateSelectorPolicy(const DisplayDevice&) const
- REQUIRES(mStateLock, kMainThreadContext);
-
// TODO(b/241285191): Look up RefreshRateSelector on Scheduler to remove redundant parameter.
status_t applyRefreshRateSelectorPolicy(PhysicalDisplayId,
- const scheduler::RefreshRateSelector&,
- bool force = false)
+ const scheduler::RefreshRateSelector&)
REQUIRES(mStateLock, kMainThreadContext);
void commitTransactionsLegacy() EXCLUDES(mStateLock) REQUIRES(kMainThreadContext);
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 89a8f92..e5d6481 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -23,6 +23,7 @@
#include "FrontEnd/LayerCreationArgs.h"
#include "renderengine/ExternalTexture.h"
+#include <common/FlagManager.h>
#include <gui/LayerState.h>
#include <system/window.h>
@@ -108,9 +109,22 @@
for (const auto& state : states) {
const bool frameRateChanged = state.state.what & layer_state_t::eFrameRateChanged;
- if (!frameRateChanged ||
- state.state.frameRateCompatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE) {
- return true;
+ if (FlagManager::getInstance().vrr_bugfix_24q4()) {
+ const bool frameRateIsNoVote = frameRateChanged &&
+ state.state.frameRateCompatibility == ANATIVEWINDOW_FRAME_RATE_NO_VOTE;
+ const bool frameRateCategoryChanged =
+ state.state.what & layer_state_t::eFrameRateCategoryChanged;
+ const bool frameRateCategoryIsNoPreference = frameRateCategoryChanged &&
+ state.state.frameRateCategory ==
+ ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE;
+ if (!frameRateIsNoVote && !frameRateCategoryIsNoPreference) {
+ return true;
+ }
+ } else {
+ if (!frameRateChanged ||
+ state.state.frameRateCompatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE) {
+ return true;
+ }
}
}
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 45b3290..121629f 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -134,6 +134,7 @@
DUMP_READ_ONLY_FLAG(screenshot_fence_preservation);
DUMP_READ_ONLY_FLAG(vulkan_renderengine);
DUMP_READ_ONLY_FLAG(renderable_buffer_usage);
+ DUMP_READ_ONLY_FLAG(vrr_bugfix_24q4);
DUMP_READ_ONLY_FLAG(restore_blur_step);
DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
DUMP_READ_ONLY_FLAG(protected_if_client);
@@ -144,6 +145,8 @@
DUMP_READ_ONLY_FLAG(deprecate_vsync_sf);
DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter);
DUMP_READ_ONLY_FLAG(detached_mirror);
+ DUMP_READ_ONLY_FLAG(commit_not_composited);
+ DUMP_READ_ONLY_FLAG(local_tonemap_screenshots);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -232,12 +235,15 @@
FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step")
FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "")
FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "")
+FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, "");
FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, "");
FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, "");
FLAG_MANAGER_READ_ONLY_FLAG(detached_mirror, "");
+FLAG_MANAGER_READ_ONLY_FLAG(commit_not_composited, "");
+FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 592e774..4cf4453 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -72,6 +72,7 @@
bool enable_layer_command_batching() const;
bool screenshot_fence_preservation() const;
bool vulkan_renderengine() const;
+ bool vrr_bugfix_24q4() const;
bool renderable_buffer_usage() const;
bool restore_blur_step() const;
bool dont_skip_on_early_ro() const;
@@ -83,6 +84,8 @@
bool deprecate_vsync_sf() const;
bool allow_n_vsyncs_in_targeter() const;
bool detached_mirror() const;
+ bool commit_not_composited() const;
+ bool local_tonemap_screenshots() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 4d3195d..5b94f07 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -22,6 +22,17 @@
} # ce_fence_promise
flag {
+ name: "commit_not_composited"
+ namespace: "core_graphics"
+ description: "mark frames as non janky if the transaction resulted in no composition"
+ bug: "340633280"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ } # commit_not_composited
+
+ flag {
name: "deprecate_vsync_sf"
namespace: "core_graphics"
description: "Depracate eVsyncSourceSurfaceFlinger and use vsync_app everywhere"
@@ -65,4 +76,23 @@
}
} # latch_unsignaled_with_auto_refresh_changed
+flag {
+ name: "local_tonemap_screenshots"
+ namespace: "core_graphics"
+ description: "Enables local tonemapping when capturing screenshots"
+ bug: "329464641"
+ is_fixed_read_only: true
+} # local_tonemap_screenshots
+
+flag {
+ name: "vrr_bugfix_24q4"
+ namespace: "core_graphics"
+ description: "bug fixes for VRR"
+ bug: "331513837"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # vrr_bugfix_24q4
+
# IMPORTANT - please keep alphabetize to reduce merge conflicts
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index ddc3967..9fd687c 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -341,6 +341,57 @@
EXPECT_NE(surfaceFrame2->getJankSeverityType(), std::nullopt);
}
+TEST_F(FrameTimelineTest, displayFrameSkippedComposition) {
+ // Layer specific increment
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_)).Times(1);
+ auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+ int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
+ auto surfaceFrame2 =
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdTwo,
+ sLayerNameTwo, sLayerNameTwo,
+ /*isBuffer*/ true, sGameMode);
+
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11);
+ surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+ mFrameTimeline->onCommitNotComposited();
+
+ EXPECT_EQ(surfaceFrame1->getActuals().presentTime, 30);
+ ASSERT_NE(surfaceFrame1->getJankType(), std::nullopt);
+ EXPECT_EQ(*surfaceFrame1->getJankType(), JankType::None);
+ ASSERT_NE(surfaceFrame1->getJankSeverityType(), std::nullopt);
+ EXPECT_EQ(*surfaceFrame1->getJankSeverityType(), JankSeverityType::None);
+
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11);
+ surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame2);
+ mFrameTimeline->setSfPresent(26, presentFence1);
+
+ auto displayFrame = getDisplayFrame(0);
+ auto& presentedSurfaceFrame2 = getSurfaceFrame(0, 0);
+ presentFence1->signalForTest(42);
+
+ // Fences haven't been flushed yet, so it should be 0
+ EXPECT_EQ(displayFrame->getActuals().presentTime, 0);
+ EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0);
+
+ addEmptyDisplayFrame();
+
+ // Fences have flushed, so the present timestamps should be updated
+ EXPECT_EQ(displayFrame->getActuals().presentTime, 42);
+ EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42);
+ EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt);
+ EXPECT_NE(surfaceFrame2->getJankSeverityType(), std::nullopt);
+}
+
TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) {
// Insert kMaxDisplayFrames' count of DisplayFrames to fill the deque
int frameTimeFactor = 0;
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index 867ff55..cfc8e99 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -461,8 +461,8 @@
HAL_PIXEL_FORMAT_RGBA_8888,
GRALLOC_USAGE_PROTECTED /*usage*/));
EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
- ftl::Flags<RequestedLayerState::Changes>(RequestedLayerState::Changes::Buffer |
- RequestedLayerState::Changes::Content)
+ ftl::Flags<RequestedLayerState::Changes>(
+ RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content)
.get());
mLifecycleManager.commitChanges();
@@ -493,10 +493,10 @@
HAL_PIXEL_FORMAT_RGB_888,
GRALLOC_USAGE_PROTECTED /*usage*/));
EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
- ftl::Flags<RequestedLayerState::Changes>(RequestedLayerState::Changes::Buffer |
- RequestedLayerState::Changes::Content |
- RequestedLayerState::Changes::VisibleRegion |
- RequestedLayerState::Changes::Visibility)
+ ftl::Flags<RequestedLayerState::Changes>(
+ RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content |
+ RequestedLayerState::Changes::VisibleRegion |
+ RequestedLayerState::Changes::Visibility)
.get());
mLifecycleManager.commitChanges();
}
@@ -580,8 +580,8 @@
HAL_PIXEL_FORMAT_RGBA_8888,
GRALLOC_USAGE_SW_READ_NEVER /*usage*/));
EXPECT_EQ(mLifecycleManager.getGlobalChanges().get(),
- ftl::Flags<RequestedLayerState::Changes>(RequestedLayerState::Changes::Buffer |
- RequestedLayerState::Changes::Content)
+ ftl::Flags<RequestedLayerState::Changes>(
+ RequestedLayerState::Changes::Buffer | RequestedLayerState::Changes::Content)
.get());
mLifecycleManager.commitChanges();
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 82adadc..23b6851 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -254,7 +254,8 @@
TEST_F(LayerSnapshotTest, FastPathClearsPreviousChangeStates) {
setColor(11, {1._hf, 0._hf, 0._hf});
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- EXPECT_EQ(getSnapshot(11)->changes, RequestedLayerState::Changes::Content);
+ EXPECT_EQ(getSnapshot(11)->changes,
+ RequestedLayerState::Changes::Content);
EXPECT_EQ(getSnapshot(11)->clientChanges, layer_state_t::eColorChanged);
EXPECT_EQ(getSnapshot(1)->changes.get(), 0u);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
@@ -264,7 +265,8 @@
TEST_F(LayerSnapshotTest, FastPathSetsChangeFlagToContent) {
setColor(1, {1._hf, 0._hf, 0._hf});
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- EXPECT_EQ(getSnapshot(1)->changes, RequestedLayerState::Changes::Content);
+ EXPECT_EQ(getSnapshot(1)->changes,
+ RequestedLayerState::Changes::Content);
EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eColorChanged);
}
@@ -278,13 +280,106 @@
transactions.back().states.front().layerId = 1;
transactions.back().states.front().state.layerId = static_cast<int32_t>(1);
mLifecycleManager.applyTransactions(transactions);
- EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::GameMode);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(),
+ RequestedLayerState::Changes::GameMode | RequestedLayerState::Changes::Metadata);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eMetadataChanged);
EXPECT_EQ(static_cast<int32_t>(getSnapshot(1)->gameMode), 42);
EXPECT_EQ(static_cast<int32_t>(getSnapshot(11)->gameMode), 42);
}
+TEST_F(LayerSnapshotTest, UpdateMetadata) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eMetadataChanged;
+ // This test focuses on metadata used by ARC++ to ensure LayerMetadata is updated correctly,
+ // and not using stale data.
+ transactions.back().states.front().state.metadata = LayerMetadata();
+ transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_UID, 123);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_WINDOW_TYPE, 234);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_TASK_ID, 345);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_MOUSE_CURSOR, 456);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_ACCESSIBILITY_ID, 567);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_PID, 678);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_CALLING_UID, 789);
+
+ transactions.back().states.front().layerId = 1;
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(1);
+
+ mLifecycleManager.applyTransactions(transactions);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::Metadata);
+
+ // Setting includeMetadata=true to ensure metadata update is applied to LayerSnapshot
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = true,
+ .displays = mFrontEndDisplayInfos,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
+ update(mSnapshotBuilder, args);
+
+ EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eMetadataChanged);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_UID, -1), 123);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_WINDOW_TYPE, -1), 234);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_TASK_ID, -1), 345);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_MOUSE_CURSOR, -1), 456);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_ACCESSIBILITY_ID, -1), 567);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_PID, -1), 678);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_CALLING_UID, -1), 789);
+}
+
+TEST_F(LayerSnapshotTest, UpdateMetadataOfHiddenLayers) {
+ hideLayer(1);
+
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eMetadataChanged;
+ // This test focuses on metadata used by ARC++ to ensure LayerMetadata is updated correctly,
+ // and not using stale data.
+ transactions.back().states.front().state.metadata = LayerMetadata();
+ transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_UID, 123);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_WINDOW_TYPE, 234);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_TASK_ID, 345);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_MOUSE_CURSOR, 456);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_ACCESSIBILITY_ID, 567);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_PID, 678);
+ transactions.back().states.front().state.metadata.setInt32(METADATA_CALLING_UID, 789);
+
+ transactions.back().states.front().layerId = 1;
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(1);
+
+ mLifecycleManager.applyTransactions(transactions);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(),
+ RequestedLayerState::Changes::Metadata | RequestedLayerState::Changes::Visibility |
+ RequestedLayerState::Changes::VisibleRegion |
+ RequestedLayerState::Changes::AffectsChildren);
+
+ // Setting includeMetadata=true to ensure metadata update is applied to LayerSnapshot
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = true,
+ .displays = mFrontEndDisplayInfos,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
+ update(mSnapshotBuilder, args);
+
+ EXPECT_EQ(static_cast<int64_t>(getSnapshot(1)->clientChanges),
+ layer_state_t::eMetadataChanged | layer_state_t::eFlagsChanged);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_UID, -1), 123);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_WINDOW_TYPE, -1), 234);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_TASK_ID, -1), 345);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_MOUSE_CURSOR, -1), 456);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_ACCESSIBILITY_ID, -1), 567);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_PID, -1), 678);
+ EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_CALLING_UID, -1), 789);
+}
+
TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) {
// ROOT
// ├── 1
@@ -1281,6 +1376,17 @@
EXPECT_TRUE(foundInputLayer);
}
+TEST_F(LayerSnapshotTest, ForEachSnapshotsWithPredicate) {
+ std::vector<uint32_t> visitedUniqueSequences;
+ mSnapshotBuilder.forEachSnapshot(
+ [&](const std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
+ visitedUniqueSequences.push_back(snapshot->uniqueSequence);
+ },
+ [](const frontend::LayerSnapshot& snapshot) { return snapshot.uniqueSequence == 111; });
+ EXPECT_EQ(visitedUniqueSequences.size(), 1u);
+ EXPECT_EQ(visitedUniqueSequences[0], 111u);
+}
+
TEST_F(LayerSnapshotTest, canOccludePresentation) {
setFlags(12, layer_state_t::eCanOccludePresentation, layer_state_t::eCanOccludePresentation);
LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 7479a4f..4fb0690 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -350,6 +350,9 @@
std::make_shared<RefreshRateSelector>(kDisplay2Modes,
kDisplay2Mode60->getId()));
+ mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
+ mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
+
using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
TestableScheduler::DisplayModeChoiceMap expectedChoices;
@@ -412,6 +415,7 @@
->registerDisplay(kDisplayId3,
std::make_shared<RefreshRateSelector>(kDisplay3Modes,
kDisplay3Mode60->getId()));
+ mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON);
const GlobalSignals globalSignals = {.touch = true};
mScheduler->replaceTouchTimer(10);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 15a6db6..078b4fe 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -327,7 +327,9 @@
return false;
}
- if (!flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) {
+ // VsyncModulator should react to mode switches on the pacesetter display.
+ if (arg->getPhysicalId() == flinger->scheduler()->pacesetterDisplayId() &&
+ !flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) {
*result_listener << "VsyncModulator did not shift to early phase";
return false;
}
@@ -368,8 +370,8 @@
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
- // Only the inner display is powered on.
- mFlinger.onActiveDisplayChanged(nullptr, *innerDisplay);
+ mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::OFF);
+ mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
@@ -385,41 +387,45 @@
0.f, 120.f)));
EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
- EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
+ EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
-
- mFlinger.commit();
-
- EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
- EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
- mFlinger.commit();
-
- EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
- EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
- innerDisplay->setPowerMode(hal::PowerMode::OFF);
- outerDisplay->setPowerMode(hal::PowerMode::ON);
-
- // Only the outer display is powered on.
- mFlinger.onActiveDisplayChanged(innerDisplay.get(), *outerDisplay);
-
- EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
- EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
-
EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
mFlinger.commit();
- EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+ EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
mFlinger.commit();
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+ mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::OFF);
+ mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
+
+ EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+ EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+ EXPECT_EQ(NO_ERROR,
+ mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
+ mock::createDisplayModeSpecs(kModeId60, false,
+ 0.f, 120.f)));
+
+ EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
+ EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60);
+
+ mFlinger.commit();
+
+ EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
+ EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+ mFlinger.commit();
+
+ EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
+ EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
}
TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) {
@@ -437,10 +443,8 @@
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
- outerDisplay->setPowerMode(hal::PowerMode::ON);
-
- // Both displays are powered on.
- mFlinger.onActiveDisplayChanged(nullptr, *innerDisplay);
+ mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
+ mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
@@ -485,7 +489,7 @@
EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
// Power off the display before the mode has been set.
- mDisplay->setPowerMode(hal::PowerMode::OFF);
+ mFlinger.setPowerModeInternal(mDisplay, hal::PowerMode::OFF);
const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
@@ -517,10 +521,8 @@
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
- outerDisplay->setPowerMode(hal::PowerMode::ON);
-
- // Both displays are powered on.
- mFlinger.onActiveDisplayChanged(nullptr, *innerDisplay);
+ mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
+ mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId60));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
@@ -539,40 +541,42 @@
EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
// Power off the outer display before the mode has been set.
- outerDisplay->setPowerMode(hal::PowerMode::OFF);
+ mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::OFF);
const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
-
- mFlinger.commit();
-
- // Powering off the inactive display should abort the mode set.
- EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
- EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
- mFlinger.commit();
-
- EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
- EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
-
- innerDisplay->setPowerMode(hal::PowerMode::OFF);
- outerDisplay->setPowerMode(hal::PowerMode::ON);
-
- // Only the outer display is powered on.
- mFlinger.onActiveDisplayChanged(innerDisplay.get(), *outerDisplay);
-
EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
mFlinger.commit();
- // The mode set should resume once the display becomes active.
- EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+ // Powering off the inactive display should not abort the mode set.
+ EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
mFlinger.commit();
EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId60));
+
+ mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::OFF);
+ mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
+
+ EXPECT_EQ(NO_ERROR,
+ mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
+ mock::createDisplayModeSpecs(kModeId120, false,
+ 0.f, 120.f)));
+
+ EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId120);
+
+ mFlinger.commit();
+
+ EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+ EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
+
+ mFlinger.commit();
+
+ EXPECT_THAT(innerDisplay, ModeSettledTo(kModeId90));
+ EXPECT_THAT(outerDisplay, ModeSettledTo(kModeId120));
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 1e02c67..198a5de 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -111,6 +111,11 @@
Scheduler::unregisterDisplay(displayId);
}
+ void setDisplayPowerMode(PhysicalDisplayId displayId, hal::PowerMode powerMode) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ Scheduler::setDisplayPowerMode(displayId, powerMode);
+ }
+
std::optional<PhysicalDisplayId> pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS {
return mPacesetterDisplayId;
}
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index 4ca0542..dec5fa5 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -30,6 +30,7 @@
MOCK_METHOD(void, onChoreographerAttached, (), (override));
MOCK_METHOD(void, onExpectedPresentTimePosted, (TimePoint, ftl::NonNull<DisplayModePtr>, Fps),
(override));
+ MOCK_METHOD(void, onCommitNotComposited, (PhysicalDisplayId), (override));
};
struct NoOpSchedulerCallback final : ISchedulerCallback {
@@ -39,6 +40,7 @@
void triggerOnFrameRateOverridesChanged() override {}
void onChoreographerAttached() override {}
void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>, Fps) override {}
+ void onCommitNotComposited(PhysicalDisplayId) override {}
};
} // namespace android::scheduler::mock