Merge "SurfaceFlinger: Layer::getFrameRate() with relatives" into rvc-dev
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 466575f..a0b9cbb 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -84,7 +84,8 @@
android::base::unique_fd bugreport_fd,
android::base::unique_fd screenshot_fd,
int bugreport_mode,
- const sp<IDumpstateListener>& listener) {
+ const sp<IDumpstateListener>& listener,
+ bool is_screenshot_requested) {
MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
// Ensure there is only one bugreport in progress at a time.
@@ -118,7 +119,7 @@
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
- screenshot_fd);
+ screenshot_fd, is_screenshot_requested);
if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) {
MYLOGE("Invalid filedescriptor");
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 6dc0225..ac8d3ac 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,7 +41,8 @@
binder::Status startBugreport(int32_t calling_uid, const std::string& calling_package,
android::base::unique_fd bugreport_fd,
android::base::unique_fd screenshot_fd, int bugreport_mode,
- const sp<IDumpstateListener>& listener) override;
+ const sp<IDumpstateListener>& listener,
+ bool is_screenshot_requested) override;
// No-op
binder::Status cancelBugreport();
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 3f359c8..ba008bb 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -64,10 +64,12 @@
* @param screenshotFd the file to which screenshot should be written
* @param bugreportMode the mode that specifies other run time options; must be one of above
* @param listener callback for updates; optional
+ * @param isScreenshotRequested indicates screenshot is requested or not
*/
void startBugreport(int callingUid, @utf8InCpp String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
- int bugreportMode, IDumpstateListener listener);
+ int bugreportMode, IDumpstateListener listener,
+ boolean isScreenshotRequested);
/*
* Cancels the bugreport currently in progress.
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 3440116..ec2b922 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1477,6 +1477,8 @@
ds.AddDir(WMTRACE_DATA_DIR, false);
}
+ ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
+
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
/* Migrate the ril_dumpstate to a device specific dumpstate? */
@@ -1605,7 +1607,6 @@
ds.AddDir(RECOVERY_DATA_DIR, true);
ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
ds.AddDir(LOGPERSIST_DATA_DIR, false);
- ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(PROFILE_DATA_DIR_CUR, true);
ds.AddDir(PROFILE_DATA_DIR_REF, true);
@@ -1728,6 +1729,8 @@
RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
if (include_sensitive_info) {
// Contains raw IP addresses, omit from reports on user builds.
RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
@@ -2246,20 +2249,21 @@
}
}
-static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
+static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
+ bool is_screenshot_requested) {
// Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
// default system screenshots.
options->bugreport_mode = ModeToString(mode);
switch (mode) {
case Dumpstate::BugreportMode::BUGREPORT_FULL:
- options->do_screenshot = true;
+ options->do_screenshot = is_screenshot_requested;
options->dumpstate_hal_mode = DumpstateMode::FULL;
break;
case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
// Currently, the dumpstate binder is only used by Shell to update progress.
options->do_start_service = true;
options->do_progress_updates = true;
- options->do_screenshot = true;
+ options->do_screenshot = is_screenshot_requested;
options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
break;
case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
@@ -2272,7 +2276,7 @@
options->do_start_service = true;
options->do_progress_updates = true;
options->do_zip_file = true;
- options->do_screenshot = true;
+ options->do_screenshot = is_screenshot_requested;
options->dumpstate_hal_mode = DumpstateMode::WEAR;
break;
// TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
@@ -2309,7 +2313,8 @@
void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
const android::base::unique_fd& bugreport_fd_in,
- const android::base::unique_fd& screenshot_fd_in) {
+ const android::base::unique_fd& screenshot_fd_in,
+ bool is_screenshot_requested) {
// In the new API world, date is always added; output is always a zip file.
// TODO(111441001): remove these options once they are obsolete.
do_add_date = true;
@@ -2319,7 +2324,7 @@
bugreport_fd.reset(dup(bugreport_fd_in.get()));
screenshot_fd.reset(dup(screenshot_fd_in.get()));
- SetOptionsFromMode(bugreport_mode, this);
+ SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
}
Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7e27787..7b8d282 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -390,7 +390,8 @@
/* Initializes options from the requested mode. */
void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd,
- const android::base::unique_fd& screenshot_fd);
+ const android::base::unique_fd& screenshot_fd,
+ bool is_screenshot_requested);
/* Returns true if the options set so far are consistent. */
bool ValidateOptions() const;
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index f26e4db..047a1c3 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -451,7 +451,7 @@
sp<DumpstateListener> listener(new DumpstateListener(dup(fileno(stdout))));
android::binder::Status status =
ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd), std::move(screenshot_fd),
- Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener);
+ Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener, true);
// startBugreport is an async call. Verify binder call succeeded first, then wait till listener
// gets expected callbacks.
EXPECT_TRUE(status.isOk());
@@ -488,7 +488,7 @@
android::binder::Status status =
ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd), std::move(screenshot_fd),
2000, // invalid bugreport mode
- listener);
+ listener, false);
EXPECT_EQ(listener->getErrorCode(), IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
// The service should have died, freeing itself up for a new invocation.
@@ -519,13 +519,13 @@
sp<DumpstateListener> listener1(new DumpstateListener(dup(fileno(stdout))));
android::binder::Status status =
ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd), std::move(screenshot_fd),
- Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener1);
+ Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener1, true);
EXPECT_TRUE(status.isOk());
// try to make another call to startBugreport. This should fail.
sp<DumpstateListener> listener2(new DumpstateListener(dup(fileno(stdout))));
status = ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd2), std::move(screenshot_fd2),
- Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener2);
+ Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener2, true);
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 0a0c40e..2efb130 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -233,7 +233,7 @@
}
TEST_F(DumpOptionsTest, InitializeFullBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_screenshot);
EXPECT_TRUE(options_.do_zip_file);
@@ -250,7 +250,7 @@
}
TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd, true);
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.do_progress_updates);
@@ -267,7 +267,7 @@
}
TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd, false);
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_zip_file);
EXPECT_TRUE(options_.is_remote_mode);
@@ -283,7 +283,7 @@
}
TEST_F(DumpOptionsTest, InitializeWearBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
EXPECT_TRUE(options_.do_add_date);
EXPECT_TRUE(options_.do_screenshot);
EXPECT_TRUE(options_.do_zip_file);
@@ -300,7 +300,7 @@
}
TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd, false);
EXPECT_TRUE(options_.do_add_date);
EXPECT_FALSE(options_.do_screenshot);
EXPECT_TRUE(options_.do_zip_file);
@@ -317,7 +317,7 @@
}
TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
- options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd);
+ options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
EXPECT_TRUE(options_.do_add_date);
EXPECT_FALSE(options_.do_screenshot);
EXPECT_TRUE(options_.do_zip_file);
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index f426dbb..fb11cee 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -406,7 +406,7 @@
return false;
}
- if (fqInstance.getPackage() == gIBaseFqName.package()) {
+ if (fqInstance.getPackage() == "android.hidl.base") {
return true; // always remove IBase from manifest
}
diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h
deleted file mode 120000
index c2047c0..0000000
--- a/include/ui/FatVector.h
+++ /dev/null
@@ -1 +0,0 @@
-../../libs/ui/include/ui/FatVector.h
\ No newline at end of file
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index aeca12b..2174ce2 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -30,24 +30,10 @@
namespace android {
-namespace {
-
-#if defined(__BRILLO__)
-// Because Brillo has no application model, security policy is managed
-// statically (at build time) with SELinux controls.
-// As a consequence, it also never runs the AppOpsManager service.
-const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED;
-#else
-const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
-#endif // defined(__BRILLO__)
-
-} // namespace
-
-static String16 _appops("appops");
-static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER;
-static sp<IBinder> gClientId;
-
static const sp<IBinder>& getClientId() {
+ static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER;
+ static sp<IBinder> gClientId;
+
pthread_mutex_lock(&gClientIdMutex);
if (gClientId == nullptr) {
gClientId = new BBinder();
@@ -56,22 +42,13 @@
return gClientId;
}
-thread_local uint64_t notedAppOpsInThisBinderTransaction[2];
-thread_local int32_t uidOfThisBinderTransaction = -1;
-
-// Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
-uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
-
AppOpsManager::AppOpsManager()
{
}
-#if defined(__BRILLO__)
-// There is no AppOpsService on Brillo
-sp<IAppOpsService> AppOpsManager::getService() { return NULL; }
-#else
sp<IAppOpsService> AppOpsManager::getService()
{
+ static String16 _appops("appops");
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
@@ -96,14 +73,13 @@
}
return service;
}
-#endif // defined(__BRILLO__)
int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
{
sp<IAppOpsService> service = getService();
return service != nullptr
? service->checkOperation(op, uid, callingPackage)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ : AppOpsManager::MODE_IGNORED;
}
int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
@@ -111,7 +87,7 @@
sp<IAppOpsService> service = getService();
return service != nullptr
? service->checkAudioOperation(op, usage, uid, callingPackage)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ : AppOpsManager::MODE_IGNORED;
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
@@ -120,12 +96,12 @@
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
- const std::unique_ptr<String16>& featureId, const String16& message) {
+ const std::unique_ptr<String16>& attributionTag, const String16& message) {
sp<IAppOpsService> service = getService();
int32_t mode = service != nullptr
- ? service->noteOperation(op, uid, callingPackage, featureId, shouldCollectNotes(op),
- message)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ ? service->noteOperation(op, uid, callingPackage, attributionTag,
+ shouldCollectNotes(op), message)
+ : AppOpsManager::MODE_IGNORED;
return mode;
}
@@ -137,13 +113,13 @@
}
int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
- bool startIfModeDefault, const std::unique_ptr<String16>& featureId,
+ bool startIfModeDefault, const std::unique_ptr<String16>& attributionTag,
const String16& message) {
sp<IAppOpsService> service = getService();
int32_t mode = service != nullptr
? service->startOperation(getClientId(), op, uid, callingPackage,
- featureId, startIfModeDefault, shouldCollectNotes(op), message)
- : APP_OPS_MANAGER_UNAVAILABLE_MODE;
+ attributionTag, startIfModeDefault, shouldCollectNotes(op), message)
+ : AppOpsManager::MODE_IGNORED;
return mode;
}
@@ -153,10 +129,10 @@
}
void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage,
- const std::unique_ptr<String16>& callingFeatureId) {
+ const std::unique_ptr<String16>& attributionTag) {
sp<IAppOpsService> service = getService();
if (service != nullptr) {
- service->finishOperation(getClientId(), op, uid, callingPackage, callingFeatureId);
+ service->finishOperation(getClientId(), op, uid, callingPackage, attributionTag);
}
}
@@ -192,6 +168,9 @@
// check it the appops needs to be collected and cache result
bool AppOpsManager::shouldCollectNotes(int32_t opcode) {
+ // Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
+ static uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
+
if (appOpsToNote[opcode] == 0) {
if (getService()->shouldCollectNotes(opcode)) {
appOpsToNote[opcode] = 2;
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 2f6e9c3..e0fb543 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -141,7 +141,7 @@
// ---------------------------------------------------------------------------
-BBinder::BBinder() : mExtras(nullptr)
+BBinder::BBinder() : mExtras(nullptr), mStability(0)
{
}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index f16c39c..d2b9b8f 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -138,6 +138,7 @@
BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
: mHandle(handle)
+ , mStability(0)
, mAlive(1)
, mObitsSent(0)
, mObituaries(nullptr)
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index a5555a3..0714723 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -47,14 +47,14 @@
}
virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
- const std::unique_ptr<String16>& featureId, bool shouldCollectAsyncNotedOp,
+ const std::unique_ptr<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
const String16& message) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
- data.writeString16(featureId);
+ data.writeString16(attributionTag);
data.writeInt32(shouldCollectAsyncNotedOp ? 1 : 0);
data.writeString16(message);
remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply);
@@ -64,7 +64,7 @@
}
virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::unique_ptr<String16>& featureId,
+ const String16& packageName, const std::unique_ptr<String16>& attributionTag,
bool startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
@@ -72,7 +72,7 @@
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
- data.writeString16(featureId);
+ data.writeString16(attributionTag);
data.writeInt32(startIfModeDefault ? 1 : 0);
data.writeInt32(shouldCollectAsyncNotedOp ? 1 : 0);
data.writeString16(message);
@@ -83,14 +83,14 @@
}
virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::unique_ptr<String16>& featureId) {
+ const String16& packageName, const std::unique_ptr<String16>& attributionTag) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(token);
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
- data.writeString16(featureId);
+ data.writeString16(attributionTag);
remote()->transact(FINISH_OPERATION_TRANSACTION, data, &reply);
}
@@ -182,11 +182,11 @@
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
- std::unique_ptr<String16> featureId;
- data.readString16(&featureId);
+ std::unique_ptr<String16> attributionTag;
+ data.readString16(&attributionTag);
bool shouldCollectAsyncNotedOp = data.readInt32() == 1;
String16 message = data.readString16();
- int32_t res = noteOperation(code, uid, packageName, featureId,
+ int32_t res = noteOperation(code, uid, packageName, attributionTag,
shouldCollectAsyncNotedOp, message);
reply->writeNoException();
reply->writeInt32(res);
@@ -198,12 +198,12 @@
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
- std::unique_ptr<String16> featureId;
- data.readString16(&featureId);
+ std::unique_ptr<String16> attributionTag;
+ data.readString16(&attributionTag);
bool startIfModeDefault = data.readInt32() == 1;
bool shouldCollectAsyncNotedOp = data.readInt32() == 1;
String16 message = data.readString16();
- int32_t res = startOperation(token, code, uid, packageName, featureId,
+ int32_t res = startOperation(token, code, uid, packageName, attributionTag,
startIfModeDefault, shouldCollectAsyncNotedOp, message);
reply->writeNoException();
reply->writeInt32(res);
@@ -215,9 +215,9 @@
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
- std::unique_ptr<String16> featureId;
- data.readString16(&featureId);
- finishOperation(token, code, uid, packageName, featureId);
+ std::unique_ptr<String16> attributionTag;
+ data.readString16(&attributionTag);
+ finishOperation(token, code, uid, packageName, attributionTag);
reply->writeNoException();
return NO_ERROR;
} break;
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 7ce5e36..e1565fa 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -15,6 +15,9 @@
*/
#include <binder/Stability.h>
+#include <binder/BpBinder.h>
+#include <binder/Binder.h>
+
namespace android {
namespace internal {
@@ -78,11 +81,12 @@
if (currentStability == stability) return OK;
- binder->attachObject(
- reinterpret_cast<void*>(&Stability::get),
- reinterpret_cast<void*>(stability),
- nullptr /*cleanupCookie*/,
- nullptr /*cleanup function*/);
+ BBinder* local = binder->localBinder();
+ if (local != nullptr) {
+ local->mStability = static_cast<int32_t>(stability);
+ } else {
+ binder->remoteBinder()->mStability = static_cast<int32_t>(stability);
+ }
return OK;
}
@@ -90,8 +94,12 @@
Stability::Level Stability::get(IBinder* binder) {
if (binder == nullptr) return UNDECLARED;
- return static_cast<Level>(reinterpret_cast<intptr_t>(
- binder->findObject(reinterpret_cast<void*>(&Stability::get))));
+ BBinder* local = binder->localBinder();
+ if (local != nullptr) {
+ return static_cast<Stability::Level>(local->mStability);
+ }
+
+ return static_cast<Stability::Level>(binder->remoteBinder()->mStability);
}
bool Stability::check(int32_t provided, Level required) {
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 5b6eb68..2ee5930 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -134,18 +134,18 @@
// const String16&) instead
int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage,
- const std::unique_ptr<String16>& featureId, const String16& message);
+ const std::unique_ptr<String16>& attributionTag, const String16& message);
// @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&,
// const String16&) instead
int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
bool startIfModeDefault);
int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
- bool startIfModeDefault, const std::unique_ptr<String16>& featureId,
+ bool startIfModeDefault, const std::unique_ptr<String16>& attributionTag,
const String16& message);
// @Deprecated, use finishOp(int32_t, int32_t, const String16&, bool, const String16&) instead
void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
void finishOp(int32_t op, int32_t uid, const String16& callingPackage,
- const std::unique_ptr<String16>& featureId);
+ const std::unique_ptr<String16>& attributionTag);
void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback);
void stopWatchingMode(const sp<IAppOpsCallback>& callback);
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 3be61f9..74e52db 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -24,6 +24,10 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace internal {
+class Stability;
+}
+
class BBinder : public IBinder
{
public:
@@ -88,7 +92,12 @@
Extras* getOrCreateExtras();
std::atomic<Extras*> mExtras;
- void* mReserved0;
+
+ friend ::android::internal::Stability;
+ union {
+ int32_t mStability;
+ void* mReserved0;
+ };
};
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7dca733..8e871b8 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -27,6 +27,10 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace internal {
+class Stability;
+};
+
using binder_proxy_limit_callback = void(*)(int);
class BpBinder : public IBinder
@@ -116,6 +120,9 @@
private:
const int32_t mHandle;
+ friend ::android::internal::Stability;
+ int32_t mStability;
+
struct Obituary {
wp<DeathRecipient> recipient;
void* cookie;
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 1b4bcce..1ffb8de 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -36,13 +36,13 @@
virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
- const std::unique_ptr<String16>& featureId, bool shouldCollectAsyncNotedOp,
+ const std::unique_ptr<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
const String16& message) = 0;
virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::unique_ptr<String16>& featureId,
+ const String16& packageName, const std::unique_ptr<String16>& attributionTag,
bool startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message) = 0;
virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::unique_ptr<String16>& featureId) = 0;
+ const String16& packageName, const std::unique_ptr<String16>& attributionTag) = 0;
virtual void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback) = 0;
virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
diff --git a/libs/binder/include/binder/Nullable.h b/libs/binder/include/binder/Nullable.h
new file mode 100644
index 0000000..b605bd3
--- /dev/null
+++ b/libs/binder/include/binder/Nullable.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <memory>
+#include <utility>
+
+namespace android {
+
+namespace aidl {
+
+// nullable/make_nullable provide source-level compatibility between std::opional and std::unique_ptr
+// usage:
+// nullable<Foo> a;
+// nullable<Foo> b = make_nullable<Foo>(...);
+// auto c = make_nullable<Foo>(...);
+// c.reset();
+// c = make_nullable<Foo>(...);
+// c = std::move(a);
+
+template <typename T>
+using nullable = std::unique_ptr<T>;
+
+template <typename T, typename... Args>
+inline nullable<T> make_nullable(Args&&... args) {
+ return std::make_unique<T>(std::forward<Args>(args)...);
+}
+
+} // namespace aidl
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 75dcdc8..649faa1 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -486,7 +486,6 @@
void AIBinder_incStrong(AIBinder* binder) {
if (binder == nullptr) {
- LOG(ERROR) << __func__ << ": on null binder";
return;
}
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 1b42b69..5b65c95 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -57,6 +57,7 @@
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
"android.hardware.biometrics.face@1.0::IBiometricsFace",
+ "android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint",
"android.hardware.bluetooth@1.0::IBluetoothHci",
"android.hardware.camera.provider@2.4::ICameraProvider",
"android.hardware.drm@1.0::IDrmFactory",
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index befabee..4809c1f 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -61,26 +61,25 @@
VNDKSP = 1,
};
-static constexpr const char* kNativeLibrariesSystemConfigPath[] = {"/etc/llndk.libraries.txt",
- "/etc/vndksp.libraries.txt"};
+static constexpr const char* kNativeLibrariesSystemConfigPath[] =
+ {"/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt",
+ "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt"};
static std::string vndkVersionStr() {
#ifdef __BIONIC__
- std::string version = android::base::GetProperty("ro.vndk.version", "");
- if (version != "" && version != "current") {
- return "." + version;
- }
+ return android::base::GetProperty("ro.vndk.version", "");
#endif
return "";
}
static void insertVndkVersionStr(std::string* fileName) {
LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
- size_t insertPos = fileName->find_last_of(".");
- if (insertPos == std::string::npos) {
- insertPos = fileName->length();
+ std::string version = vndkVersionStr();
+ size_t pos = fileName->find("{}");
+ while (pos != std::string::npos) {
+ fileName->replace(pos, 2, version);
+ pos = fileName->find("{}", pos + version.size());
}
- fileName->insert(insertPos, vndkVersionStr());
}
static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
@@ -103,11 +102,7 @@
}
static const std::string getSystemNativeLibraries(NativeLibrary type) {
- static const char* androidRootEnv = getenv("ANDROID_ROOT");
- static const std::string rootDir = androidRootEnv != nullptr ? androidRootEnv : "/system";
-
- std::string nativeLibrariesSystemConfig = rootDir + kNativeLibrariesSystemConfigPath[type];
-
+ std::string nativeLibrariesSystemConfig = kNativeLibrariesSystemConfigPath[type];
insertVndkVersionStr(&nativeLibrariesSystemConfig);
std::vector<std::string> soNames;
diff --git a/libs/gui/BufferHubConsumer.cpp b/libs/gui/BufferHubConsumer.cpp
index 0ddb87e..b5cdeb2 100644
--- a/libs/gui/BufferHubConsumer.cpp
+++ b/libs/gui/BufferHubConsumer.cpp
@@ -147,16 +147,6 @@
return INVALID_OPERATION;
}
-status_t BufferHubConsumer::setFrameRate(float /*frameRate*/) {
- ALOGE("BufferHubConsumer::setFrameRate: not implemented.");
- return INVALID_OPERATION;
-}
-
-status_t BufferHubConsumer::getFrameRate(float* /*frameRate*/) const {
- ALOGE("BufferHubConsumer::getFrameRate: not implemented.");
- return INVALID_OPERATION;
-}
-
status_t BufferHubConsumer::dumpState(const String8& /*prefix*/, String8* /*outResult*/) const {
ALOGE("BufferHubConsumer::dumpState: not implemented.");
return INVALID_OPERATION;
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 4435265..da6143c 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -783,18 +783,6 @@
return NO_ERROR;
}
-status_t BufferQueueConsumer::setFrameRate(float frameRate) {
- std::lock_guard<std::mutex> lock(mCore->mMutex);
- mCore->mFrameRate = frameRate;
- return NO_ERROR;
-}
-
-status_t BufferQueueConsumer::getFrameRate(float* frameRate) const {
- std::lock_guard<std::mutex> lock(mCore->mMutex);
- *frameRate = mCore->mFrameRate;
- return NO_ERROR;
-}
-
status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const {
struct passwd* pwd = getpwnam("shell");
uid_t shellUid = pwd ? pwd->pw_uid : 0;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 9e5d681..a1803d8 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -130,8 +130,7 @@
mLastQueuedSlot(INVALID_BUFFER_SLOT),
mUniqueId(getUniqueId()),
mAutoPrerotation(false),
- mTransformHintInUse(0),
- mFrameRate(0) {
+ mTransformHintInUse(0) {
int numStartingBuffers = getMaxBufferCountLocked();
for (int s = 0; s < numStartingBuffers; s++) {
mFreeSlots.insert(s);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 9e86838..3f4c5da 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1676,14 +1676,4 @@
return NO_ERROR;
}
-status_t BufferQueueProducer::setFrameRate(float frameRate) {
- ATRACE_CALL();
- BQ_LOGV("setFrameRate: %.0f", frameRate);
-
- std::lock_guard<std::mutex> lock(mCore->mMutex);
-
- mCore->mFrameRate = frameRate;
- return NO_ERROR;
-}
-
} // namespace android
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 515f45c..9f91d9d 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -363,24 +363,6 @@
return OK;
}
-status_t ConsumerBase::setFrameRate(float frameRate) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- CB_LOGE("setFrameRate: ConsumerBase is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setFrameRate(frameRate);
-}
-
-status_t ConsumerBase::getFrameRate(float* frameRate) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- CB_LOGE("getFrameRate: ConsumerBase is abandoned!");
- return NO_INIT;
- }
- return mConsumer->getFrameRate(frameRate);
-}
-
void ConsumerBase::dumpState(String8& result) const {
dumpState(result, "");
}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 2521a7c..c705d39 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -51,8 +51,6 @@
GET_SIDEBAND_STREAM,
GET_OCCUPANCY_HISTORY,
DISCARD_FREE_BUFFERS,
- SET_FRAME_RATE,
- GET_FRAME_RATE,
DUMP_STATE,
LAST = DUMP_STATE,
};
@@ -165,16 +163,6 @@
Tag::DISCARD_FREE_BUFFERS);
}
- status_t setFrameRate(float frameRate) override {
- using Signature = decltype(&IGraphicBufferConsumer::setFrameRate);
- return callRemote<Signature>(Tag::SET_FRAME_RATE, frameRate);
- }
-
- status_t getFrameRate(float* frameRate) const override {
- using Signature = decltype(&IGraphicBufferConsumer::getFrameRate);
- return callRemote<Signature>(Tag::GET_FRAME_RATE, frameRate);
- }
-
status_t dumpState(const String8& prefix, String8* outResult) const override {
using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
return callRemote<Signature>(Tag::DUMP_STATE, prefix, outResult);
@@ -232,10 +220,6 @@
return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory);
case Tag::DISCARD_FREE_BUFFERS:
return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers);
- case Tag::SET_FRAME_RATE:
- return callLocal(data, reply, &IGraphicBufferConsumer::setFrameRate);
- case Tag::GET_FRAME_RATE:
- return callLocal(data, reply, &IGraphicBufferConsumer::getFrameRate);
case Tag::DUMP_STATE: {
using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
return callLocal<Signature>(data, reply, &IGraphicBufferConsumer::dumpState);
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 7b5596e..ad00939 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -74,7 +74,6 @@
GET_CONSUMER_USAGE,
SET_LEGACY_BUFFER_DROP,
SET_AUTO_PREROTATION,
- SET_FRAME_RATE,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -560,14 +559,6 @@
}
return result;
}
-
- virtual status_t setFrameRate(float frameRate) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeFloat(frameRate);
- status_t result = remote()->transact(SET_FRAME_RATE, data, &reply, IBinder::FLAG_ONEWAY);
- return result;
- }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -700,8 +691,6 @@
status_t setAutoPrerotation(bool autoPrerotation) override {
return mBase->setAutoPrerotation(autoPrerotation);
}
-
- status_t setFrameRate(float frameRate) override { return mBase->setFrameRate(frameRate); }
};
IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
@@ -721,12 +710,6 @@
return INVALID_OPERATION;
}
-status_t IGraphicBufferProducer::setFrameRate(float frameRate) {
- // No-op for IGBP other than BufferQueue.
- (void)frameRate;
- return INVALID_OPERATION;
-}
-
status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
status_t res = OK;
res = parcel->writeUint32(USE_BUFFER_QUEUE);
@@ -1096,13 +1079,6 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case SET_FRAME_RATE: {
- CHECK_INTERFACE(IGraphicBuffer, data, reply);
- float frameRate = data.readFloat();
- status_t result = setFrameRate(frameRate);
- reply->writeInt32(result);
- return NO_ERROR;
- }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 915ebf9..8d79cf8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1280,6 +1280,9 @@
std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles;
int numExcludeHandles = data.readInt32();
+ if (numExcludeHandles >= static_cast<int>(MAX_LAYERS)) {
+ return BAD_VALUE;
+ }
excludeHandles.reserve(numExcludeHandles);
for (int i = 0; i < numExcludeHandles; i++) {
excludeHandles.emplace(data.readStrongBinder());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index a9c9b74..f7158d0 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -443,39 +443,18 @@
// ------------------------------- InputWindowCommands ----------------------------------------
void InputWindowCommands::merge(const InputWindowCommands& other) {
- transferTouchFocusCommands
- .insert(transferTouchFocusCommands.end(),
- std::make_move_iterator(other.transferTouchFocusCommands.begin()),
- std::make_move_iterator(other.transferTouchFocusCommands.end()));
-
syncInputWindows |= other.syncInputWindows;
}
void InputWindowCommands::clear() {
- transferTouchFocusCommands.clear();
syncInputWindows = false;
}
void InputWindowCommands::write(Parcel& output) const {
- output.writeUint32(static_cast<uint32_t>(transferTouchFocusCommands.size()));
- for (const auto& transferTouchFocusCommand : transferTouchFocusCommands) {
- output.writeStrongBinder(transferTouchFocusCommand.fromToken);
- output.writeStrongBinder(transferTouchFocusCommand.toToken);
- }
-
output.writeBool(syncInputWindows);
}
void InputWindowCommands::read(const Parcel& input) {
- size_t count = input.readUint32();
- transferTouchFocusCommands.clear();
- for (size_t i = 0; i < count; i++) {
- TransferTouchFocusCommand transferTouchFocusCommand;
- transferTouchFocusCommand.fromToken = input.readStrongBinder();
- transferTouchFocusCommand.toToken = input.readStrongBinder();
- transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
- }
-
syncInputWindows = input.readBool();
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index dc4860a..2307fbf 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1290,15 +1290,6 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transferTouchFocus(
- const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
- InputWindowCommands::TransferTouchFocusCommand transferTouchFocusCommand;
- transferTouchFocusCommand.fromToken = fromToken;
- transferTouchFocusCommand.toToken = toToken;
- mInputWindowCommands.transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
- return *this;
-}
-
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() {
mInputWindowCommands.syncInputWindows = true;
return *this;
diff --git a/libs/gui/include/gui/BufferHubConsumer.h b/libs/gui/include/gui/BufferHubConsumer.h
index d756203..d380770 100644
--- a/libs/gui/include/gui/BufferHubConsumer.h
+++ b/libs/gui/include/gui/BufferHubConsumer.h
@@ -93,12 +93,6 @@
// See |IGraphicBufferConsumer::discardFreeBuffers|
status_t discardFreeBuffers() override;
- // See |IGraphicBufferConsumer::setFrameRate|
- status_t setFrameRate(float frameRate) override;
-
- // See |IGraphicBufferConsumer::getFrameRate|
- status_t getFrameRate(float* frameRate) const override;
-
// See |IGraphicBufferConsumer::dumpState|
status_t dumpState(const String8& prefix, String8* outResult) const override;
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index e9f0449..7db69ec 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -149,12 +149,6 @@
// See IGraphicBufferConsumer::discardFreeBuffers
virtual status_t discardFreeBuffers() override;
- // See IGraphicBufferConsumer::setFrameRate.
- virtual status_t setFrameRate(float frameRate) override;
-
- // See IGraphicBufferConsumer::getFrameRate.
- virtual status_t getFrameRate(float* frameRate) const override;
-
// dump our state in a String
status_t dumpState(const String8& prefix, String8* outResult) const override;
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 05c2074..557c28b 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -354,9 +354,6 @@
// mTransformHintInUse is to cache the mTransformHint used by the producer.
uint32_t mTransformHintInUse;
- // The frame rate the app intends to run at.
- float mFrameRate;
-
}; // class BufferQueueCore
} // namespace android
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index cbace5b..a7f7d1d 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -198,9 +198,6 @@
// See IGraphicBufferProducer::setAutoPrerotation
virtual status_t setAutoPrerotation(bool autoPrerotation);
- // See IGraphicBufferProducer::setFrameRate
- virtual status_t setFrameRate(float frameRate) override;
-
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index cfed9aa..8ff0cd0 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -111,12 +111,6 @@
// See IGraphicBufferConsumer::discardFreeBuffers
status_t discardFreeBuffers();
- // See IGraphicBufferConsumer::setFrameRate
- status_t setFrameRate(float frameRate);
-
- // See IGraphicBufferConsumer::getFrameRate
- status_t getFrameRate(float* frameRate);
-
private:
ConsumerBase(const ConsumerBase&);
void operator=(const ConsumerBase&);
diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
index 56fe949..0b92e7d 100644
--- a/libs/gui/include/gui/IGraphicBufferConsumer.h
+++ b/libs/gui/include/gui/IGraphicBufferConsumer.h
@@ -275,16 +275,6 @@
// call to free up any of its locally cached buffers.
virtual status_t discardFreeBuffers() = 0;
- // Set the frame rate the producer will run at.
- //
- // Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setFrameRate(float frameRate) = 0;
-
- // Get the frame rate the producer will run at.
- //
- // Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t getFrameRate(float* frameRate) const = 0;
-
// dump state into a string
virtual status_t dumpState(const String8& prefix, String8* outResult) const = 0;
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 87989da..d7f3492 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -639,9 +639,6 @@
// the width and height used for dequeueBuffer will be additionally swapped.
virtual status_t setAutoPrerotation(bool autoPrerotation);
- // Sets the apps intended frame rate.
- virtual status_t setFrameRate(float frameRate);
-
#ifndef NO_BINDER
// Static method exports any IGraphicBufferProducer object to a parcel. It
// handles null producer as well.
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 0659f0d..09487ea 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -76,6 +76,8 @@
public:
DECLARE_META_INTERFACE(SurfaceComposer)
+ static constexpr size_t MAX_LAYERS = 4096;
+
// flags for setTransactionState()
enum {
eSynchronous = 0x01,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 7e3d5d5..2b2f773 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -271,12 +271,6 @@
};
struct InputWindowCommands {
- struct TransferTouchFocusCommand {
- sp<IBinder> fromToken;
- sp<IBinder> toToken;
- };
-
- std::vector<TransferTouchFocusCommand> transferTouchFocusCommands;
bool syncInputWindows{false};
void merge(const InputWindowCommands& other);
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index ad7cbfe..917c0d4 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -178,7 +178,6 @@
status_t getUniqueId(uint64_t* outId) const;
status_t getConsumerUsage(uint64_t* outUsage) const;
- // See IGraphicBufferProducer::setFrameRate
status_t setFrameRate(float frameRate, int8_t compatibility);
protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0cf141d..2fb9538 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -507,7 +507,6 @@
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
- Transaction& transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
Transaction& syncInputWindows();
#endif
diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
index e940cf3..98f24c2 100644
--- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h
+++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
@@ -49,8 +49,6 @@
MOCK_CONST_METHOD1(getSidebandStream, status_t(sp<NativeHandle>*));
MOCK_METHOD2(getOccupancyHistory, status_t(bool, std::vector<OccupancyTracker::Segment>*));
MOCK_METHOD0(discardFreeBuffers, status_t());
- MOCK_METHOD1(setFrameRate, status_t(float));
- MOCK_CONST_METHOD1(getFrameRate, status_t(float*));
MOCK_CONST_METHOD2(dumpState, status_t(const String8&, String8*));
};
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 0f7e2fb..0ff33ac 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -185,9 +185,18 @@
}
void Choreographer::scheduleCallbacks() {
- AutoMutex _{mLock};
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- if (mFrameCallbacks.top().dueTime <= now) {
+ const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ nsecs_t dueTime;
+ {
+ AutoMutex _{mLock};
+ // If there are no pending callbacks then don't schedule a vsync
+ if (mFrameCallbacks.empty()) {
+ return;
+ }
+ dueTime = mFrameCallbacks.top().dueTime;
+ }
+
+ if (dueTime <= now) {
ALOGV("choreographer %p ~ scheduling vsync", this);
scheduleVsync();
return;
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 416ebfe..e73f245 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -381,15 +381,6 @@
LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
}
- const uint16_t protTexData[] = {0};
- glGenTextures(1, &mProtectedTexName);
- glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
-
// mColorBlindnessCorrection = M;
if (mUseColorManagement) {
@@ -966,9 +957,13 @@
return NO_ERROR;
}
- if (bufferFence.get() >= 0 && !waitFence(std::move(bufferFence))) {
- ATRACE_NAME("Waiting before draw");
- sync_wait(bufferFence.get(), -1);
+ if (bufferFence.get() >= 0) {
+ // Duplicate the fence for passing to waitFence.
+ base::unique_fd bufferFenceDup(dup(bufferFence.get()));
+ if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
+ ATRACE_NAME("Waiting before draw");
+ sync_wait(bufferFence.get(), -1);
+ }
}
if (buffer == nullptr) {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 4cd0b3d..32dbad1 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -178,7 +178,6 @@
EGLSurface mDummySurface;
EGLContext mProtectedEGLContext;
EGLSurface mProtectedDummySurface;
- GLuint mProtectedTexName;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
GLuint mVpWidth;
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 6fd4b80..d8e4059 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -77,6 +77,7 @@
outDescriptorInfo->layerCount = layerCount;
outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
outDescriptorInfo->usage = usage;
+ outDescriptorInfo->reservedSize = 0;
}
} // anonymous namespace
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index cd2a448..bf487c4 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -67,20 +67,19 @@
// ----------------------------------------------------------------------------
Region::Region() {
- mStorage.push_back(Rect(0, 0));
+ mStorage.add(Rect(0,0));
}
Region::Region(const Region& rhs)
+ : mStorage(rhs.mStorage)
{
- mStorage.clear();
- mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
#if defined(VALIDATE_REGIONS)
validate(rhs, "rhs copy-ctor");
#endif
}
Region::Region(const Rect& rhs) {
- mStorage.push_back(rhs);
+ mStorage.add(rhs);
}
Region::~Region()
@@ -101,8 +100,8 @@
* final, correctly ordered region buffer. Each rectangle will be compared with the span directly
* above it, and subdivided to resolve any remaining T-junctions.
*/
-static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst,
- int spanDirection) {
+static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end,
+ Vector<Rect>& dst, int spanDirection) {
dst.clear();
const Rect* current = end - 1;
@@ -110,7 +109,7 @@
// add first span immediately
do {
- dst.push_back(*current);
+ dst.add(*current);
current--;
} while (current->top == lastTop && current >= begin);
@@ -148,12 +147,12 @@
if (prev.right <= left) break;
if (prev.right > left && prev.right < right) {
- dst.push_back(Rect(prev.right, top, right, bottom));
+ dst.add(Rect(prev.right, top, right, bottom));
right = prev.right;
}
if (prev.left > left && prev.left < right) {
- dst.push_back(Rect(prev.left, top, right, bottom));
+ dst.add(Rect(prev.left, top, right, bottom));
right = prev.left;
}
@@ -167,12 +166,12 @@
if (prev.left >= right) break;
if (prev.left > left && prev.left < right) {
- dst.push_back(Rect(left, top, prev.left, bottom));
+ dst.add(Rect(left, top, prev.left, bottom));
left = prev.left;
}
if (prev.right > left && prev.right < right) {
- dst.push_back(Rect(left, top, prev.right, bottom));
+ dst.add(Rect(left, top, prev.right, bottom));
left = prev.right;
}
// if an entry in the previous span is too far left, nothing further right in the
@@ -184,7 +183,7 @@
}
if (left < right) {
- dst.push_back(Rect(left, top, right, bottom));
+ dst.add(Rect(left, top, right, bottom));
}
current--;
@@ -202,14 +201,13 @@
if (r.isEmpty()) return r;
if (r.isRect()) return r;
- FatVector<Rect> reversed;
+ Vector<Rect> reversed;
reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL);
Region outputRegion;
- reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(),
- outputRegion.mStorage, direction_LTR);
- outputRegion.mStorage.push_back(
- r.getBounds()); // to make region valid, mStorage must end with bounds
+ reverseRectsResolvingJunctions(reversed.begin(), reversed.end(),
+ outputRegion.mStorage, direction_LTR);
+ outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
#if defined(VALIDATE_REGIONS)
validate(outputRegion, "T-Junction free region");
@@ -224,8 +222,7 @@
validate(*this, "this->operator=");
validate(rhs, "rhs.operator=");
#endif
- mStorage.clear();
- mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
+ mStorage = rhs.mStorage;
return *this;
}
@@ -234,7 +231,7 @@
if (mStorage.size() >= 2) {
const Rect bounds(getBounds());
mStorage.clear();
- mStorage.push_back(bounds);
+ mStorage.add(bounds);
}
return *this;
}
@@ -258,25 +255,25 @@
void Region::clear()
{
mStorage.clear();
- mStorage.push_back(Rect(0, 0));
+ mStorage.add(Rect(0,0));
}
void Region::set(const Rect& r)
{
mStorage.clear();
- mStorage.push_back(r);
+ mStorage.add(r);
}
void Region::set(int32_t w, int32_t h)
{
mStorage.clear();
- mStorage.push_back(Rect(w, h));
+ mStorage.add(Rect(w, h));
}
void Region::set(uint32_t w, uint32_t h)
{
mStorage.clear();
- mStorage.push_back(Rect(w, h));
+ mStorage.add(Rect(w, h));
}
bool Region::isTriviallyEqual(const Region& region) const {
@@ -302,7 +299,8 @@
void Region::addRectUnchecked(int l, int t, int r, int b)
{
Rect rect(l,t,r,b);
- mStorage.insert(mStorage.end() - 1, rect);
+ size_t where = mStorage.size() - 1;
+ mStorage.insertAt(rect, where, 1);
}
// ----------------------------------------------------------------------------
@@ -352,7 +350,7 @@
Region& Region::scaleSelf(float sx, float sy) {
size_t count = mStorage.size();
- Rect* rects = mStorage.data();
+ Rect* rects = mStorage.editArray();
while (count) {
rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
@@ -457,10 +455,10 @@
class Region::rasterizer : public region_operator<Rect>::region_rasterizer
{
Rect bounds;
- FatVector<Rect>& storage;
+ Vector<Rect>& storage;
Rect* head;
Rect* tail;
- FatVector<Rect> span;
+ Vector<Rect> span;
Rect* cur;
public:
explicit rasterizer(Region& reg)
@@ -487,8 +485,8 @@
flushSpan();
}
if (storage.size()) {
- bounds.top = storage.front().top;
- bounds.bottom = storage.back().bottom;
+ bounds.top = storage.itemAt(0).top;
+ bounds.bottom = storage.top().bottom;
if (storage.size() == 1) {
storage.clear();
}
@@ -496,7 +494,7 @@
bounds.left = 0;
bounds.right = 0;
}
- storage.push_back(bounds);
+ storage.add(bounds);
}
void Region::rasterizer::operator()(const Rect& rect)
@@ -511,15 +509,15 @@
return;
}
}
- span.push_back(rect);
- cur = span.data() + (span.size() - 1);
+ span.add(rect);
+ cur = span.editArray() + (span.size() - 1);
}
void Region::rasterizer::flushSpan()
{
bool merge = false;
if (tail-head == ssize_t(span.size())) {
- Rect const* p = span.data();
+ Rect const* p = span.editArray();
Rect const* q = head;
if (p->top == q->bottom) {
merge = true;
@@ -534,17 +532,17 @@
}
}
if (merge) {
- const int bottom = span.front().bottom;
+ const int bottom = span[0].bottom;
Rect* r = head;
while (r != tail) {
r->bottom = bottom;
r++;
}
} else {
- bounds.left = min(span.front().left, bounds.left);
- bounds.right = max(span.back().right, bounds.right);
- storage.insert(storage.end(), span.begin(), span.end());
- tail = storage.data() + storage.size();
+ bounds.left = min(span.itemAt(0).left, bounds.left);
+ bounds.right = max(span.top().right, bounds.right);
+ storage.appendVector(span);
+ tail = storage.editArray() + storage.size();
head = tail - span.size();
}
span.clear();
@@ -552,7 +550,7 @@
bool Region::validate(const Region& reg, const char* name, bool silent)
{
- if (reg.mStorage.empty()) {
+ if (reg.mStorage.isEmpty()) {
ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name);
// return immediately as the code below assumes mStorage is non-empty
return false;
@@ -691,8 +689,9 @@
}
sk_dst.op(sk_lhs, sk_rhs, sk_op);
- if (sk_dst.empty() && dst.empty()) return;
-
+ if (sk_dst.isEmpty() && dst.isEmpty())
+ return;
+
bool same = true;
Region::const_iterator head = dst.begin();
Region::const_iterator const tail = dst.end();
@@ -787,7 +786,7 @@
validate(reg, "translate (before)");
#endif
size_t count = reg.mStorage.size();
- Rect* rects = reg.mStorage.data();
+ Rect* rects = reg.mStorage.editArray();
while (count) {
rects->offsetBy(dx, dy);
rects++;
@@ -867,25 +866,24 @@
ALOGE("Region::unflatten() failed, invalid region");
return BAD_VALUE;
}
- mStorage.clear();
- mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end());
+ mStorage = result.mStorage;
return NO_ERROR;
}
// ----------------------------------------------------------------------------
Region::const_iterator Region::begin() const {
- return mStorage.data();
+ return mStorage.array();
}
Region::const_iterator Region::end() const {
// Workaround for b/77643177
// mStorage should never be empty, but somehow it is and it's causing
// an abort in ubsan
- if (mStorage.empty()) return mStorage.data();
+ if (mStorage.isEmpty()) return mStorage.array();
size_t numRects = isRect() ? 1 : mStorage.size() - 1;
- return mStorage.data() + numRects;
+ return mStorage.array() + numRects;
}
Rect const* Region::getArray(size_t* count) const {
diff --git a/libs/ui/include/ui/FatVector.h b/libs/ui/include/ui/FatVector.h
deleted file mode 100644
index 25fe3a0..0000000
--- a/libs/ui/include/ui/FatVector.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_REGION_FAT_VECTOR_H
-#define ANDROID_REGION_FAT_VECTOR_H
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <utils/Log.h>
-#include <type_traits>
-
-#include <vector>
-
-namespace android {
-
-template <typename T, size_t SIZE = 4>
-class InlineStdAllocator {
-public:
- struct Allocation {
- private:
- Allocation(const Allocation&) = delete;
- void operator=(const Allocation&) = delete;
-
- public:
- Allocation() {}
- // char array instead of T array, so memory is uninitialized, with no destructors run
- char array[sizeof(T) * SIZE];
- bool inUse = false;
- };
-
- typedef T value_type; // needed to implement std::allocator
- typedef T* pointer; // needed to implement std::allocator
-
- explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
- InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
- ~InlineStdAllocator() {}
-
- T* allocate(size_t num, const void* = 0) {
- if (!mAllocation.inUse && num <= SIZE) {
- mAllocation.inUse = true;
- return static_cast<T*>(static_cast<void*>(mAllocation.array));
- } else {
- return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T))));
- }
- }
-
- void deallocate(pointer p, size_t) {
- if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) {
- mAllocation.inUse = false;
- } else {
- // 'free' instead of delete here - destruction handled separately
- free(p);
- }
- }
- Allocation& mAllocation;
-};
-
-/**
- * std::vector with SIZE elements preallocated into an internal buffer.
- *
- * Useful for avoiding the cost of malloc in cases where only SIZE or
- * fewer elements are needed in the common case.
- */
-template <typename T, size_t SIZE = 4>
-class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
-public:
- FatVector()
- : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) {
- this->reserve(SIZE);
- }
-
- explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
-
-private:
- typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
-};
-
-} // namespace android
-
-#endif // ANDROID_REGION_FAT_VECTOR_H
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 6bb7b8d..2db3b10 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -21,13 +21,13 @@
#include <sys/types.h>
#include <ostream>
+#include <utils/Vector.h>
+
#include <ui/Rect.h>
#include <utils/Flattenable.h>
#include <android-base/macros.h>
-#include "FatVector.h"
-
#include <string>
namespace android {
@@ -180,7 +180,7 @@
// with an extra Rect as the last element which is set to the
// bounds of the region. However, if the region is
// a simple Rect then mStorage contains only that rect.
- FatVector<Rect> mStorage;
+ Vector<Rect> mStorage;
};
@@ -235,3 +235,4 @@
}; // namespace android
#endif // ANDROID_UI_REGION_H
+
diff --git a/libs/ui/include_vndk/ui/FatVector.h b/libs/ui/include_vndk/ui/FatVector.h
deleted file mode 120000
index bf30166..0000000
--- a/libs/ui/include_vndk/ui/FatVector.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/ui/FatVector.h
\ No newline at end of file
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 67d69b4..a58e87c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -158,13 +158,16 @@
// NOTE: This is only valid if the backend is OpenGL
attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
attrs.push_back(vendorEGL);
+
+ // Context virtualization is only available on GL back-end.
+ // Needed to support threading with GL back-end
+ attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
+ attrs.push_back(EGL_FALSE);
break;
default:
- ALOGV("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
+ ALOGE("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
break;
}
- attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
- attrs.push_back(EGL_FALSE);
return true;
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index d30c4f1..1f283b1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1445,7 +1445,6 @@
ASSERT_EQ(keyArgs.action, verifiedKey.action);
ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
- ASSERT_EQ(keyArgs.eventTime, verifiedKey.eventTimeNanos);
ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
@@ -1453,6 +1452,43 @@
ASSERT_EQ(0, verifiedKey.repeatCount);
}
+TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+ mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&motionArgs);
+
+ InputEvent* event = window->consume();
+ ASSERT_NE(event, nullptr);
+
+ std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
+ ASSERT_NE(verified, nullptr);
+ ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
+
+ EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
+ EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
+ EXPECT_EQ(motionArgs.source, verified->source);
+ EXPECT_EQ(motionArgs.displayId, verified->displayId);
+
+ const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
+
+ EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
+ EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
+ EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
+ EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
+ EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
+ EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
+ EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
+}
+
class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
protected:
static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index 3e0f136..b0d3e3b 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -9,7 +9,7 @@
],
aidl: {
- local_include_dirs: ["."],
+ local_include_dirs: ["include"],
include_dirs: [
"frameworks/base/core/java/android/os",
],
@@ -28,6 +28,11 @@
"-Wunused",
"-Wunreachable-code",
],
+
+ local_include_dirs: ["include"],
+ export_include_dirs: [
+ "include",
+ ],
}
cc_test {
diff --git a/include/android/CoolingDevice.h b/services/powermanager/include/android/CoolingDevice.h
similarity index 100%
rename from include/android/CoolingDevice.h
rename to services/powermanager/include/android/CoolingDevice.h
diff --git a/include/android/Temperature.h b/services/powermanager/include/android/Temperature.h
similarity index 100%
rename from include/android/Temperature.h
rename to services/powermanager/include/android/Temperature.h
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d7ec868..e4d754c 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -485,6 +485,10 @@
}
}
+ if (recomputeVisibleRegions == true) {
+ maybeDirtyInput();
+ }
+
return true;
}
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index f5a99ca..4e5c593 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -346,8 +346,6 @@
mPreviousBufferId = getCurrentBufferId();
mBufferInfo.mBuffer =
mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);
- auto* layerCompositionState = editCompositionState();
- layerCompositionState->buffer = mBufferInfo.mBuffer;
if (mBufferInfo.mBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
@@ -441,7 +439,7 @@
mQueueItemCondition.broadcast();
}
- mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
item.mGraphicBuffer->getHeight(), item.mFrameNumber);
mFlinger->signalLayerUpdate();
@@ -564,8 +562,6 @@
mBufferInfo.mApi = mConsumer->getCurrentApi();
mBufferInfo.mPixelFormat = mFormat;
mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
- float latchedFrameRate;
- mConsumer->getFrameRate(&latchedFrameRate);
}
sp<Layer> BufferQueueLayer::createClone() {
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index de5429b..3ed6889 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -616,7 +616,6 @@
mPreviousBufferId = getCurrentBufferId();
mBufferInfo.mBuffer = s.buffer;
mBufferInfo.mFence = s.acquireFence;
- editCompositionState()->buffer = mBufferInfo.mBuffer;
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index 9aaef65..f24f314 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -104,9 +104,8 @@
return static_cast<uint16_t>(value >> 40);
}
-DisplayId DisplayId::fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) {
- return {(static_cast<Type>(manufacturerId) << 40) | (static_cast<Type>(displayNameHash) << 8) |
- port};
+DisplayId DisplayId::fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t modelHash) {
+ return {(static_cast<Type>(manufacturerId) << 40) | (static_cast<Type>(modelHash) << 8) | port};
}
bool isEdid(const DisplayIdentificationData& data) {
@@ -209,23 +208,30 @@
view.remove_prefix(kDescriptorLength);
}
- if (displayName.empty()) {
+ std::string_view modelString = displayName;
+
+ if (modelString.empty()) {
ALOGW("Invalid EDID: falling back to serial number due to missing display name.");
- displayName = serialNumber;
+ modelString = serialNumber;
}
- if (displayName.empty()) {
+ if (modelString.empty()) {
ALOGW("Invalid EDID: falling back to ASCII text due to missing serial number.");
- displayName = asciiText;
+ modelString = asciiText;
}
- if (displayName.empty()) {
+ if (modelString.empty()) {
ALOGE("Invalid EDID: display name and fallback descriptors are missing.");
return {};
}
+ // Hash model string instead of using product code or (integer) serial number, since the latter
+ // have been observed to change on some displays with multiple inputs.
+ const auto modelHash = static_cast<uint32_t>(std::hash<std::string_view>()(modelString));
+
return Edid{.manufacturerId = manufacturerId,
- .pnpId = *pnpId,
- .displayName = displayName,
.productId = productId,
+ .pnpId = *pnpId,
+ .modelHash = modelHash,
+ .displayName = displayName,
.manufactureWeek = manufactureWeek,
.manufactureOrModelYear = manufactureOrModelYear};
}
@@ -253,10 +259,8 @@
return {};
}
- // Hash display name instead of using product code or serial number, since the latter have been
- // observed to change on some displays with multiple inputs.
- const auto hash = static_cast<uint32_t>(std::hash<std::string_view>()(edid->displayName));
- return DisplayIdentificationInfo{.id = DisplayId::fromEdid(port, edid->manufacturerId, hash),
+ const auto displayId = DisplayId::fromEdid(port, edid->manufacturerId, edid->modelHash);
+ return DisplayIdentificationInfo{.id = displayId,
.name = std::string(edid->displayName),
.deviceProductInfo = buildDeviceProductInfo(*edid)};
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index 0a18ba1..d91b957 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -34,7 +34,7 @@
uint16_t manufacturerId() const;
- static DisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash);
+ static DisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t modelHash);
};
inline bool operator==(DisplayId lhs, DisplayId rhs) {
@@ -61,6 +61,7 @@
uint16_t manufacturerId;
uint16_t productId;
PnpId pnpId;
+ uint32_t modelHash;
std::string_view displayName;
uint8_t manufactureOrModelYear;
uint8_t manufactureWeek;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 36544b6..aeffb0e 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -57,9 +57,12 @@
*/
FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer)
+ const sp<IGraphicBufferConsumer>& consumer,
+ uint32_t maxWidth, uint32_t maxHeight)
: ConsumerBase(consumer),
mDisplayId(displayId),
+ mMaxWidth(maxWidth),
+ mMaxHeight(maxHeight),
mCurrentBufferSlot(-1),
mCurrentBuffer(),
mCurrentFence(Fence::NO_FENCE),
@@ -75,14 +78,16 @@
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
const auto& activeConfig = mHwc.getActiveConfig(displayId);
- mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
- activeConfig->getHeight());
+ ui::Size limitedSize =
+ limitFramebufferSize(activeConfig->getWidth(), activeConfig->getHeight());
+ mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
mConsumer->setMaxAcquiredBufferCount(
SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}
-void FramebufferSurface::resizeBuffers(const uint32_t width, const uint32_t height) {
- mConsumer->setDefaultBufferSize(width, height);
+void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) {
+ ui::Size limitedSize = limitFramebufferSize(width, height);
+ mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
}
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
@@ -177,6 +182,29 @@
}
}
+ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) {
+ // TODO(b/149495759): Use the ui::Size constructor once it no longer is broken.
+ ui::Size framebufferSize;
+ framebufferSize.width = width;
+ framebufferSize.height = height;
+ bool wasLimited = true;
+ if (width > mMaxWidth && mMaxWidth != 0) {
+ float aspectRatio = float(width) / float(height);
+ framebufferSize.height = mMaxWidth / aspectRatio;
+ framebufferSize.width = mMaxWidth;
+ wasLimited = true;
+ }
+ if (height > mMaxHeight && mMaxHeight != 0) {
+ float aspectRatio = float(width) / float(height);
+ framebufferSize.height = mMaxHeight;
+ framebufferSize.width = mMaxHeight * aspectRatio;
+ wasLimited = true;
+ }
+ ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
+ framebufferSize.width, framebufferSize.height, width, height);
+ return framebufferSize;
+}
+
void FramebufferSurface::dumpAsString(String8& result) const {
Mutex::Autolock lock(mMutex);
result.appendFormat(" FramebufferSurface: dataspace: %s(%d)\n",
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 7f451a5..a1859f3 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -23,6 +23,7 @@
#include <compositionengine/DisplaySurface.h>
#include <compositionengine/impl/HwcBufferCache.h>
#include <gui/ConsumerBase.h>
+#include <ui/Size.h>
#include "DisplayIdentification.h"
@@ -39,7 +40,8 @@
class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, DisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer);
+ const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
+ uint32_t maxHeight);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
@@ -47,7 +49,7 @@
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(const uint32_t width, const uint32_t height);
+ virtual void resizeBuffers(uint32_t width, uint32_t height);
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
@@ -58,6 +60,9 @@
virtual void dumpLocked(String8& result, const char* prefix) const;
+ // Limits the width and height by the maximum width specified in the constructor.
+ ui::Size limitFramebufferSize(uint32_t width, uint32_t height);
+
// nextBuffer waits for and then latches the next buffer from the
// BufferQueue and releases the previously latched buffer to the
// BufferQueue. The new buffer is returned in the 'buffer' argument.
@@ -66,6 +71,14 @@
const DisplayId mDisplayId;
+ // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
+ // the device.
+ const uint32_t mMaxWidth;
+
+ // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
+ // the device.
+ const uint32_t mMaxHeight;
+
// mCurrentBufferIndex is the slot index of the current buffer or
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
// or the buffer is not associated with a slot.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b952eb6..d8229c6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -994,6 +994,9 @@
commitTransaction(c);
mPendingStatesSnapshot = mPendingStates;
mCurrentState.callbackHandles = {};
+
+ maybeDirtyInput();
+
return flags;
}
@@ -2537,6 +2540,32 @@
}
}
+bool Layer::maybeDirtyInput() {
+ // No sense redirtying input.
+ if (mFlinger->inputDirty()) return true;
+
+ if (hasInput()) {
+ mFlinger->dirtyInput();
+ return true;
+ }
+
+ // If a child or relative dirties the input, no sense continuing to traverse
+ // so we return early and halt the recursion. We traverse ourselves instead
+ // of using traverse() so we can implement this early halt.
+ for (const sp<Layer>& child : mDrawingChildren) {
+ if (child->maybeDirtyInput()) {
+ return true;
+ }
+ }
+ for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+ sp<Layer> relative = weakRelative.promote();
+ if (relative && relative->maybeDirtyInput()) {
+ return true;
+ }
+ }
+ return false;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 72f6de3..be80f78 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1002,6 +1002,10 @@
// Window types from WindowManager.LayoutParams
const int mWindowType;
+ // Called when mDrawingState has changed. If we or one of our children/relatives hasInput()
+ // then we will dirty the setInputWindows cache.
+ bool maybeDirtyInput();
+
private:
/**
* Returns an unsorted vector of all layers that are part of this tree.
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index d3364a0..e6c8654 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -120,7 +120,7 @@
// We latch the transparent region here, instead of above where we latch
// the rest of the geometry because it is only content but not necessarily
// resize dependent.
- if (!mFront.activeTransparentRegion_legacy.isTriviallyEqual(
+ if (!mFront.activeTransparentRegion_legacy.hasSameRects(
mFront.requestedTransparentRegion_legacy)) {
mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 40a63d7..5009e10 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -162,10 +162,6 @@
return mProducer->setAutoPrerotation(autoPrerotation);
}
-status_t MonitoredProducer::setFrameRate(float frameRate) {
- return mProducer->setFrameRate(frameRate);
-}
-
IBinder* MonitoredProducer::onAsBinder() {
return this;
}
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 4bda831..788919b 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -71,7 +71,6 @@
virtual status_t getUniqueId(uint64_t* outId) const override;
virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
virtual status_t setAutoPrerotation(bool autoPrerotation) override;
- virtual status_t setFrameRate(float frameRate) override;
// The Layer which created this producer, and on which queued Buffer's will be displayed.
sp<Layer> getLayer() const;
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 682679c..c675971 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -168,9 +168,9 @@
}
void RefreshRateOverlay::primeCache() {
- auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
+ auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
if (allRefreshRates.size() == 1) {
- auto fps = allRefreshRates.begin()->second.fps;
+ auto fps = allRefreshRates.begin()->second->fps;
half4 color = {LOW_FPS_COLOR, ALPHA};
mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
return;
@@ -178,8 +178,8 @@
std::vector<uint32_t> supportedFps;
supportedFps.reserve(allRefreshRates.size());
- for (auto [ignored, refreshRate] : allRefreshRates) {
- supportedFps.push_back(refreshRate.fps);
+ for (auto& [ignored, refreshRate] : allRefreshRates) {
+ supportedFps.push_back(refreshRate->fps);
}
std::sort(supportedFps.begin(), supportedFps.end());
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 0031d70..68cd84f 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -201,9 +201,10 @@
void RegionSamplingThread::addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) {
- wp<Layer> stopLayer = stopLayerHandle != nullptr
- ? static_cast<Layer::Handle*>(stopLayerHandle.get())->owner
- : nullptr;
+ wp<Layer> stopLayer;
+ if (stopLayerHandle != nullptr && stopLayerHandle->localBinder() != nullptr) {
+ stopLayer = static_cast<Layer::Handle*>(stopLayerHandle.get())->owner;
+ }
sp<IBinder> asBinder = IInterface::asBinder(listener);
asBinder->linkToDeath(this);
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index 101060c..8b08592 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -212,7 +212,5 @@
for (const auto& [layer, info] : activeLayers()) {
info->clearHistory();
}
-
- mActiveLayersEnd = 0;
}
} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 63d9c4b..c04447d 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -71,10 +71,10 @@
std::unordered_map<float, Offsets> offsets;
for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) {
- if (refreshRate.fps > 65.0f) {
- offsets.emplace(refreshRate.fps, getHighFpsOffsets(refreshRate.vsyncPeriod));
+ if (refreshRate->fps > 65.0f) {
+ offsets.emplace(refreshRate->fps, getHighFpsOffsets(refreshRate->vsyncPeriod));
} else {
- offsets.emplace(refreshRate.fps, getDefaultOffsets(refreshRate.vsyncPeriod));
+ offsets.emplace(refreshRate->fps, getDefaultOffsets(refreshRate->vsyncPeriod));
}
}
return offsets;
@@ -238,7 +238,7 @@
refreshRates.reserve(allRefreshRates.size());
for (const auto& [ignored, refreshRate] : allRefreshRates) {
- refreshRates.emplace_back(refreshRate.fps);
+ refreshRates.emplace_back(refreshRate->fps);
}
return refreshRates;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 15b158d..02d0b53 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -23,6 +23,9 @@
#include <chrono>
#include <cmath>
+#undef LOG_TAG
+#define LOG_TAG "RefreshRateConfigs"
+
namespace android::scheduler {
using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
@@ -95,22 +98,19 @@
}
const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2(
- const std::vector<LayerRequirement>& layers, bool touchActive) const {
+ const std::vector<LayerRequirement>& layers, bool touchActive,
+ bool* touchConsidered) const {
ATRACE_CALL();
ALOGV("getRefreshRateForContent %zu layers", layers.size());
+ *touchConsidered = false;
std::lock_guard lock(mLock);
- // For now if the touch is active return the peak refresh rate
- // This should be optimized to consider other layers as well.
- if (touchActive) {
- return *mAvailableRefreshRates.back();
- }
-
// If there are not layers, there is not content detection, so return the current
// refresh rate.
if (layers.empty()) {
- return getCurrentRefreshRateByPolicyLocked();
+ *touchConsidered = touchActive;
+ return touchActive ? *mAvailableRefreshRates.back() : getCurrentRefreshRateByPolicyLocked();
}
int noVoteLayers = 0;
@@ -118,17 +118,30 @@
int maxVoteLayers = 0;
int explicitDefaultVoteLayers = 0;
int explicitExactOrMultipleVoteLayers = 0;
+ float maxExplicitWeight = 0;
for (const auto& layer : layers) {
- if (layer.vote == LayerVoteType::NoVote)
+ if (layer.vote == LayerVoteType::NoVote) {
noVoteLayers++;
- else if (layer.vote == LayerVoteType::Min)
+ } else if (layer.vote == LayerVoteType::Min) {
minVoteLayers++;
- else if (layer.vote == LayerVoteType::Max)
+ } else if (layer.vote == LayerVoteType::Max) {
maxVoteLayers++;
- else if (layer.vote == LayerVoteType::ExplicitDefault)
+ } else if (layer.vote == LayerVoteType::ExplicitDefault) {
explicitDefaultVoteLayers++;
- else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple)
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
explicitExactOrMultipleVoteLayers++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ }
+ }
+
+ // Consider the touch event if there are no ExplicitDefault layers.
+ // ExplicitDefault are mostly interactive (as opposed to ExplicitExactOrMultiple)
+ // and therefore if those posted an explicit vote we should not change it
+ // if get get a touch event.
+ if (touchActive && explicitDefaultVoteLayers == 0) {
+ *touchConsidered = true;
+ return *mAvailableRefreshRates.back();
}
// Only if all layers want Min we should return Min
@@ -168,16 +181,17 @@
const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate);
if (layer.vote == LayerVoteType::ExplicitDefault) {
const auto layerScore = [&]() {
- const auto [displayFramesQuot, displayFramesRem] =
- getDisplayFrames(layerPeriod, displayPeriod);
- if (displayFramesQuot == 0) {
- // Layer desired refresh rate is higher the display rate.
- return static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod);
+ // Find the actual rate the layer will render, assuming
+ // that layerPeriod is the minimal time to render a frame
+ auto actualLayerPeriod = displayPeriod;
+ int multiplier = 1;
+ while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
+ multiplier++;
+ actualLayerPeriod = displayPeriod * multiplier;
}
-
- return 1.0f -
- (static_cast<float>(displayFramesRem) /
- static_cast<float>(layerPeriod));
+ return std::min(1.0f,
+ static_cast<float>(layerPeriod) /
+ static_cast<float>(actualLayerPeriod));
}();
ALOGV("%s (ExplicitDefault, weight %.2f) %.2fHz gives %s score of %.2f",
@@ -240,6 +254,7 @@
template <typename Iter>
const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
+ constexpr auto EPSILON = 0.001f;
const RefreshRate* bestRefreshRate = begin->first;
float max = begin->second;
for (auto i = begin; i != end; ++i) {
@@ -248,7 +263,7 @@
ATRACE_INT(refreshRate->name.c_str(), round<int>(score * 100));
- if (score > max) {
+ if (score > max * (1 + EPSILON)) {
max = score;
bestRefreshRate = refreshRate;
}
@@ -286,12 +301,12 @@
mCurrentRefreshRate) != mAvailableRefreshRates.end()) {
return *mCurrentRefreshRate;
}
- return mRefreshRates.at(mDefaultConfig);
+ return *mRefreshRates.at(mDefaultConfig);
}
void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
std::lock_guard lock(mLock);
- mCurrentRefreshRate = &mRefreshRates.at(configId);
+ mCurrentRefreshRate = mRefreshRates.at(configId).get();
}
RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs,
@@ -326,7 +341,7 @@
if (mRefreshRates.count(defaultConfigId) == 0) {
return BAD_VALUE;
}
- const RefreshRate& refreshRate = mRefreshRates.at(defaultConfigId);
+ const RefreshRate& refreshRate = *mRefreshRates.at(defaultConfigId);
if (!refreshRate.inPolicy(minRefreshRate, maxRefreshRate)) {
return BAD_VALUE;
}
@@ -361,10 +376,10 @@
outRefreshRates->clear();
outRefreshRates->reserve(mRefreshRates.size());
for (const auto& [type, refreshRate] : mRefreshRates) {
- if (shouldAddRefreshRate(refreshRate)) {
+ if (shouldAddRefreshRate(*refreshRate)) {
ALOGV("getSortedRefreshRateList: config %d added to list policy",
- refreshRate.configId.value());
- outRefreshRates->push_back(&refreshRate);
+ refreshRate->configId.value());
+ outRefreshRates->push_back(refreshRate.get());
}
}
@@ -376,7 +391,7 @@
void RefreshRateConfigs::constructAvailableRefreshRates() {
// Filter configs based on current policy and sort based on vsync period
- HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig).configGroup;
+ HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig)->configGroup;
ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps);
getSortedRefreshRateList(
@@ -403,16 +418,15 @@
LOG_ALWAYS_FATAL_IF(configs.empty());
LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size());
- auto buildRefreshRate = [&](InputConfig config) -> RefreshRate {
- const float fps = 1e9f / config.vsyncPeriod;
- return RefreshRate(config.configId, config.vsyncPeriod, config.configGroup,
- base::StringPrintf("%2.ffps", fps), fps);
- };
-
for (const auto& config : configs) {
- mRefreshRates.emplace(config.configId, buildRefreshRate(config));
+ const float fps = 1e9f / config.vsyncPeriod;
+ mRefreshRates.emplace(config.configId,
+ std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod,
+ config.configGroup,
+ base::StringPrintf("%2.ffps", fps),
+ fps));
if (config.configId == currentHwcConfig) {
- mCurrentRefreshRate = &mRefreshRates.at(config.configId);
+ mCurrentRefreshRate = mRefreshRates.at(config.configId).get();
}
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index c8aec86..87d4389 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -59,6 +59,8 @@
configGroup(configGroup),
name(std::move(name)),
fps(fps) {}
+
+ RefreshRate(const RefreshRate&) = delete;
// This config ID corresponds to the position of the config in the vector that is stored
// on the device.
const HwcConfigIndexType configId;
@@ -85,7 +87,8 @@
bool operator==(const RefreshRate& other) const { return !(*this != other); }
};
- using AllRefreshRatesMapType = std::unordered_map<HwcConfigIndexType, const RefreshRate>;
+ using AllRefreshRatesMapType =
+ std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>;
// Sets the current policy to choose refresh rates. Returns NO_ERROR if the requested policy is
// valid, or a negative error value otherwise. policyChanged, if non-null, will be set to true
@@ -134,9 +137,11 @@
// Returns the refresh rate that fits best to the given layers. This function also gets a
// boolean flag that indicates whether user touched the screen recently to be factored in when
- // choosing the refresh rate.
+ // choosing the refresh rate and returns whether the refresh rate was chosen as a result of
+ // a touch event.
const RefreshRate& getRefreshRateForContentV2(const std::vector<LayerRequirement>& layers,
- bool touchActive) const EXCLUDES(mLock);
+ bool touchActive, bool* touchConsidered) const
+ EXCLUDES(mLock);
// Returns all the refresh rates supported by the device. This won't change at runtime.
const AllRefreshRatesMapType& getAllRefreshRates() const EXCLUDES(mLock);
@@ -163,7 +168,7 @@
// Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at
// runtime.
const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const {
- return mRefreshRates.at(configId);
+ return *mRefreshRates.at(configId);
};
// Stores the current configId the device operates at
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5444239..920f0ec 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -463,7 +463,7 @@
return;
}
mFeatures.configId = newConfigId;
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
+ auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
}
}
@@ -483,7 +483,7 @@
// that is currently on top. b/142507166 will give us this capability.
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (mLayerHistory) {
- mLayerHistory->clear();
+ // Layer History will be cleared based on RefreshRateConfigs::getRefreshRateForContentV2
mTouchTimer->reset();
@@ -515,7 +515,7 @@
// TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
// magic number
- const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+ const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f;
if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// If we're not in performance mode then the kernel timer shouldn't do
@@ -620,10 +620,21 @@
return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId;
}
- return mRefreshRateConfigs
- .getRefreshRateForContentV2(mFeatures.contentRequirements,
- mTouchTimer && mFeatures.touch == TouchState::Active)
- .configId;
+ bool touchConsidered;
+ const auto& ret =
+ mRefreshRateConfigs
+ .getRefreshRateForContentV2(mFeatures.contentRequirements,
+ mTouchTimer &&
+ mFeatures.touch == TouchState::Active,
+ &touchConsidered)
+ .configId;
+ if (touchConsidered) {
+ // Clear layer history if refresh rate was selected based on touch to allow
+ // the hueristic to pick up with the new rate.
+ mLayerHistory->clear();
+ }
+
+ return ret;
}
std::optional<HwcConfigIndexType> Scheduler::getPreferredConfigId() {
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 949ba4c..8987dcd 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -19,8 +19,10 @@
#define LOG_TAG "VSyncReactor"
//#define LOG_NDEBUG 0
#include "VSyncReactor.h"
+#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Trace.h>
+#include "../TracedOrdinal.h"
#include "TimeKeeper.h"
#include "VSyncDispatch.h"
#include "VSyncTracker.h"
@@ -32,12 +34,35 @@
return systemTime(SYSTEM_TIME_MONOTONIC);
}
+class PredictedVsyncTracer {
+public:
+ PredictedVsyncTracer(VSyncDispatch& dispatch)
+ : mRegistration(dispatch,
+ std::bind(&PredictedVsyncTracer::callback, this, std::placeholders::_1,
+ std::placeholders::_2),
+ "PredictedVsyncTracer") {
+ mRegistration.schedule(0, 0);
+ }
+
+private:
+ TracedOrdinal<bool> mParity = {"VSYNC-predicted", 0};
+ VSyncCallbackRegistration mRegistration;
+
+ void callback(nsecs_t /*vsyncTime*/, nsecs_t /*targetWakeupTim*/) {
+ mParity = !mParity;
+ mRegistration.schedule(0, 0);
+ }
+};
+
VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit)
: mClock(std::move(clock)),
mTracker(std::move(tracker)),
mDispatch(std::move(dispatch)),
- mPendingLimit(pendingFenceLimit) {}
+ mPendingLimit(pendingFenceLimit),
+ mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false)
+ ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
+ : nullptr) {}
VSyncReactor::~VSyncReactor() = default;
@@ -287,7 +312,7 @@
auto it = mCallbacks.find(callback);
if (it == mCallbacks.end()) {
// TODO (b/146557561): resolve lastCallbackTime semantics in DispSync i/f.
- static auto constexpr maxListeners = 3;
+ static auto constexpr maxListeners = 4;
if (mCallbacks.size() >= maxListeners) {
ALOGE("callback %s not added, exceeded callback limit of %i (currently %zu)", name,
maxListeners, mCallbacks.size());
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h
index aa8a38d..7d8a8e3 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.h
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.h
@@ -30,6 +30,7 @@
class VSyncDispatch;
class VSyncTracker;
class CallbackRepeater;
+class PredictedVsyncTracer;
// TODO (b/145217110): consider renaming.
class VSyncReactor : public android::DispSync {
@@ -86,6 +87,8 @@
std::unordered_map<DispSync::Callback*, std::unique_ptr<CallbackRepeater>> mCallbacks
GUARDED_BY(mMutex);
+
+ const std::unique_ptr<PredictedVsyncTracer> mPredictedVsyncTracer;
};
class SystemClock : public Clock {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 67b02c8..cfaabfc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -217,6 +217,8 @@
bool SurfaceFlinger::hasSyncFramework;
bool SurfaceFlinger::useVrFlinger;
int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
+uint32_t SurfaceFlinger::maxGraphicsWidth;
+uint32_t SurfaceFlinger::maxGraphicsHeight;
bool SurfaceFlinger::hasWideColorDisplay;
ui::Rotation SurfaceFlinger::internalDisplayOrientation = ui::ROTATION_0;
bool SurfaceFlinger::useColorManagement;
@@ -283,6 +285,9 @@
maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2);
+ maxGraphicsWidth = std::max(max_graphics_width(0), 0);
+ maxGraphicsHeight = std::max(max_graphics_height(0), 0);
+
hasWideColorDisplay = has_wide_color_display(false);
useColorManagement = use_color_management(false);
@@ -359,15 +364,12 @@
property_get("ro.surface_flinger.supports_background_blur", value, "0");
bool supportsBlurs = atoi(value);
- property_get("debug.sf.disable_blurs", value, "0");
- bool disableBlurs = atoi(value);
- mEnableBlurs = supportsBlurs && !disableBlurs;
- ALOGI_IF(!mEnableBlurs, "Disabling blur effects. supported: %d, disabled: %d", supportsBlurs,
- disableBlurs);
+ mSupportsBlur = supportsBlurs;
+ ALOGI_IF(!mSupportsBlur, "Disabling blur effects, they are not supported.");
property_get("ro.sf.blurs_are_expensive", value, "0");
mBlursAreExpensive = atoi(value);
- const size_t defaultListSize = MAX_LAYERS;
+ const size_t defaultListSize = ISurfaceComposer::MAX_LAYERS;
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
@@ -404,6 +406,7 @@
void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
{
// the window manager died on us. prepare its eulogy.
+ mBootFinished = false;
// restore initial conditions (default device unblank, etc)
initializeDisplays();
@@ -520,6 +523,11 @@
void SurfaceFlinger::bootFinished()
{
+ if (mBootFinished == true) {
+ ALOGE("Extra call to bootFinished");
+ return;
+ }
+ mBootFinished = true;
if (mStartPropertySetThread->join() != NO_ERROR) {
ALOGE("Join StartPropertySetThread failed!");
}
@@ -614,7 +622,7 @@
.setUseColorManagerment(useColorManagement)
.setEnableProtectedContext(enable_protected_contents(false))
.setPrecacheToneMapperShaderOnly(false)
- .setSupportsBackgroundBlur(mEnableBlurs)
+ .setSupportsBackgroundBlur(mSupportsBlur)
.setContextPriority(useContextPriority
? renderengine::RenderEngine::ContextPriority::HIGH
: renderengine::RenderEngine::ContextPriority::MEDIUM)
@@ -696,6 +704,11 @@
property_get("persist.sys.sf.color_mode", value, "0");
mForceColorMode = static_cast<ColorMode>(atoi(value));
+
+ property_get("persist.sys.sf.disable_blurs", value, "0");
+ bool disableBlurs = atoi(value);
+ mDisableBlurs = disableBlurs;
+ ALOGI_IF(disableBlurs, "Disabling blur effects, user preference.");
}
void SurfaceFlinger::startBootAnim() {
@@ -903,18 +916,27 @@
void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
ATRACE_CALL();
- auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
+ auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str());
- // Don't check against the current mode yet. Worst case we set the desired
- // config twice. However event generation config might have changed so we need to update it
- // accordingly
std::lock_guard<std::mutex> lock(mActiveConfigLock);
- const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event;
- mDesiredActiveConfig = info;
- mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
+ if (mDesiredActiveConfigChanged) {
+ // If a config change is pending, just cache the latest request in
+ // mDesiredActiveConfig
+ const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event;
+ mDesiredActiveConfig = info;
+ mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
+ } else {
+ // Check is we are already at the desired config
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (!display || display->getActiveConfig() == refreshRate.configId) {
+ return;
+ }
- if (!mDesiredActiveConfigChanged) {
+ // Initiate a config change.
+ mDesiredActiveConfigChanged = true;
+ mDesiredActiveConfig = info;
+
// This will trigger HWC refresh without resetting the idle timer.
repaintEverythingForHWC();
// Start receiving vsync samples now, so that we can detect a period
@@ -927,7 +949,6 @@
mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
}
- mDesiredActiveConfigChanged = true;
if (mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(refreshRate);
@@ -976,7 +997,7 @@
mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
display->setActiveConfig(mUpcomingActiveConfig.configId);
- auto refreshRate =
+ auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId);
mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
@@ -996,7 +1017,7 @@
mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfigChanged = false;
- auto const refreshRate =
+ const auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId);
mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod);
mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
@@ -1029,7 +1050,7 @@
desiredActiveConfig = mDesiredActiveConfig;
}
- auto refreshRate =
+ auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId);
ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(),
refreshRate.name.c_str());
@@ -1066,7 +1087,9 @@
mUpcomingActiveConfig.configId.value(),
constraints, &outTimeline);
if (status != NO_ERROR) {
- LOG_ALWAYS_FATAL("setActiveConfigWithConstraints failed: %d", status);
+ // setActiveConfigWithConstraints may fail if a hotplug event is just about
+ // to be sent. We just log the error in this case.
+ ALOGW("setActiveConfigWithConstraints failed: %d", status);
return false;
}
@@ -2362,13 +2385,14 @@
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
- const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface,
+ const DisplayDeviceState& state,
+ const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer) {
auto displayId = compositionDisplay->getDisplayId();
DisplayDeviceCreationArgs creationArgs(this, displayToken, compositionDisplay);
creationArgs.sequenceId = state.sequenceId;
creationArgs.isSecure = state.isSecure;
- creationArgs.displaySurface = dispSurface;
+ creationArgs.displaySurface = displaySurface;
creationArgs.hasWideColorGamut = false;
creationArgs.supportedPerFrameMetadata = 0;
@@ -2444,6 +2468,140 @@
return display;
}
+void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
+ const DisplayDeviceState& state) {
+ int width = 0;
+ int height = 0;
+ ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
+ if (state.physical) {
+ const auto& activeConfig =
+ getCompositionEngine().getHwComposer().getActiveConfig(state.physical->id);
+ width = activeConfig->getWidth();
+ height = activeConfig->getHeight();
+ pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
+ } else if (state.surface != nullptr) {
+ int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+ ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
+ status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
+ int intPixelFormat;
+ status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
+ ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
+ pixelFormat = static_cast<ui::PixelFormat>(intPixelFormat);
+ } else {
+ // Virtual displays without a surface are dormant:
+ // they have external state (layer stack, projection,
+ // etc.) but no internal state (i.e. a DisplayDevice).
+ return;
+ }
+
+ compositionengine::DisplayCreationArgsBuilder builder;
+ if (const auto& physical = state.physical) {
+ builder.setPhysical({physical->id, physical->type});
+ }
+ builder.setPixels(ui::Size(width, height));
+ builder.setPixelFormat(pixelFormat);
+ builder.setIsSecure(state.isSecure);
+ builder.setLayerStackId(state.layerStack);
+ builder.setPowerAdvisor(&mPowerAdvisor);
+ builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer());
+ builder.setName(state.displayName);
+ const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
+
+ sp<compositionengine::DisplaySurface> displaySurface;
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferProducer> bqProducer;
+ sp<IGraphicBufferConsumer> bqConsumer;
+ getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);
+
+ std::optional<DisplayId> displayId = compositionDisplay->getId();
+
+ if (state.isVirtual()) {
+ sp<VirtualDisplaySurface> vds =
+ new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer,
+ bqConsumer, state.displayName);
+
+ displaySurface = vds;
+ producer = vds;
+ } else {
+ ALOGE_IF(state.surface != nullptr,
+ "adding a supported display, but rendering "
+ "surface is provided (%p), ignoring it",
+ state.surface.get());
+
+ LOG_ALWAYS_FATAL_IF(!displayId);
+ displaySurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer,
+ maxGraphicsWidth, maxGraphicsHeight);
+ producer = bqProducer;
+ }
+
+ if (displaySurface != nullptr) {
+ mDisplays.emplace(displayToken,
+ setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
+ displaySurface, producer));
+ if (!state.isVirtual()) {
+ LOG_ALWAYS_FATAL_IF(!displayId);
+ dispatchDisplayHotplugEvent(displayId->value, true);
+ }
+
+ const auto displayDevice = mDisplays[displayToken];
+ if (displayDevice->isPrimary()) {
+ mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() *
+ displayDevice->getHeight());
+ }
+ }
+}
+
+void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) {
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
+ // Save display ID before disconnecting.
+ const auto displayId = display->getId();
+ display->disconnect();
+
+ if (!display->isVirtual()) {
+ LOG_ALWAYS_FATAL_IF(!displayId);
+ dispatchDisplayHotplugEvent(displayId->value, false);
+ }
+ }
+
+ mDisplays.erase(displayToken);
+}
+
+void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
+ const DisplayDeviceState& currentState,
+ const DisplayDeviceState& drawingState) {
+ const sp<IBinder> currentBinder = IInterface::asBinder(currentState.surface);
+ const sp<IBinder> drawingBinder = IInterface::asBinder(drawingState.surface);
+ if (currentBinder != drawingBinder) {
+ // changing the surface is like destroying and recreating the DisplayDevice
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
+ display->disconnect();
+ }
+ mDisplays.erase(displayToken);
+ processDisplayAdded(displayToken, currentState);
+ return;
+ }
+
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
+ if (currentState.layerStack != drawingState.layerStack) {
+ display->setLayerStack(currentState.layerStack);
+ }
+ if ((currentState.orientation != drawingState.orientation) ||
+ (currentState.viewport != drawingState.viewport) ||
+ (currentState.frame != drawingState.frame)) {
+ display->setProjection(currentState.orientation, currentState.viewport,
+ currentState.frame);
+ }
+ if (currentState.width != drawingState.width ||
+ currentState.height != drawingState.height) {
+ display->setDisplaySize(currentState.width, currentState.height);
+ if (display->isPrimary()) {
+ mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height);
+ }
+ }
+ }
+}
+
void SurfaceFlinger::processDisplayChangesLocked() {
// here we take advantage of Vector's copy-on-write semantics to
// improve performance by skipping the transaction entirely when
@@ -2452,158 +2610,31 @@
const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
- const size_t cc = curr.size();
- size_t dc = draw.size();
// find the displays that were removed
// (ie: in drawing state but not in current state)
// also handle displays that changed
// (ie: displays that are in both lists)
- for (size_t i = 0; i < dc;) {
- const ssize_t j = curr.indexOfKey(draw.keyAt(i));
+ for (size_t i = 0; i < draw.size(); i++) {
+ const wp<IBinder>& displayToken = draw.keyAt(i);
+ const ssize_t j = curr.indexOfKey(displayToken);
if (j < 0) {
// in drawing state but not in current state
- if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
- // Save display ID before disconnecting.
- const auto displayId = display->getId();
- display->disconnect();
-
- if (!display->isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, false);
- }
- }
-
- mDisplays.erase(draw.keyAt(i));
+ processDisplayRemoved(displayToken);
} else {
// this display is in both lists. see if something changed.
- const DisplayDeviceState& state(curr[j]);
- const wp<IBinder>& displayToken = curr.keyAt(j);
- const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
- const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
- if (state_binder != draw_binder) {
- // changing the surface is like destroying and
- // recreating the DisplayDevice, so we just remove it
- // from the drawing state, so that it get re-added
- // below.
- if (const auto display = getDisplayDeviceLocked(displayToken)) {
- display->disconnect();
- }
- mDisplays.erase(displayToken);
- mDrawingState.displays.removeItemsAt(i);
- dc--;
- // at this point we must loop to the next item
- continue;
- }
-
- if (const auto display = getDisplayDeviceLocked(displayToken)) {
- if (state.layerStack != draw[i].layerStack) {
- display->setLayerStack(state.layerStack);
- }
- if ((state.orientation != draw[i].orientation) ||
- (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) {
- display->setProjection(state.orientation, state.viewport, state.frame);
- }
- if (state.width != draw[i].width || state.height != draw[i].height) {
- display->setDisplaySize(state.width, state.height);
- if (display->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(state.width * state.height);
- }
- }
- }
+ const DisplayDeviceState& currentState = curr[j];
+ const DisplayDeviceState& drawingState = draw[i];
+ processDisplayChanged(displayToken, currentState, drawingState);
}
- ++i;
}
// find displays that were added
// (ie: in current state but not in drawing state)
- for (size_t i = 0; i < cc; i++) {
- if (draw.indexOfKey(curr.keyAt(i)) < 0) {
- const DisplayDeviceState& state(curr[i]);
-
- int width = 0;
- int height = 0;
- ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
- if (state.physical) {
- const auto& activeConfig =
- getCompositionEngine().getHwComposer().getActiveConfig(
- state.physical->id);
- width = activeConfig->getWidth();
- height = activeConfig->getHeight();
- pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
- } else if (state.surface != nullptr) {
- int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
- ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
- status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
- ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
- int intPixelFormat;
- status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
- ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
- pixelFormat = static_cast<ui::PixelFormat>(intPixelFormat);
- } else {
- // Virtual displays without a surface are dormant:
- // they have external state (layer stack, projection,
- // etc.) but no internal state (i.e. a DisplayDevice).
- continue;
- }
-
- compositionengine::DisplayCreationArgsBuilder builder;
- if (const auto& physical = state.physical) {
- builder.setPhysical({physical->id, physical->type});
- }
- builder.setPixels(ui::Size(width, height));
- builder.setPixelFormat(pixelFormat);
- builder.setIsSecure(state.isSecure);
- builder.setLayerStackId(state.layerStack);
- builder.setPowerAdvisor(&mPowerAdvisor);
- builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays ||
- getHwComposer().isUsingVrComposer());
- builder.setName(state.displayName);
- auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
-
- sp<compositionengine::DisplaySurface> dispSurface;
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferProducer> bqProducer;
- sp<IGraphicBufferConsumer> bqConsumer;
- getFactory().createBufferQueue(&bqProducer, &bqConsumer, false);
-
- std::optional<DisplayId> displayId = compositionDisplay->getId();
-
- if (state.isVirtual()) {
- sp<VirtualDisplaySurface> vds =
- new VirtualDisplaySurface(getHwComposer(), displayId, state.surface,
- bqProducer, bqConsumer, state.displayName);
-
- dispSurface = vds;
- producer = vds;
- } else {
- ALOGE_IF(state.surface != nullptr,
- "adding a supported display, but rendering "
- "surface is provided (%p), ignoring it",
- state.surface.get());
-
- LOG_ALWAYS_FATAL_IF(!displayId);
- dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer);
- producer = bqProducer;
- }
-
- const wp<IBinder>& displayToken = curr.keyAt(i);
- if (dispSurface != nullptr) {
- mDisplays.emplace(displayToken,
- setupNewDisplayDeviceInternal(displayToken,
- compositionDisplay, state,
- dispSurface, producer));
- if (!state.isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, true);
- }
-
- const auto displayDevice = mDisplays[displayToken];
- if (displayDevice->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() *
- displayDevice->getHeight());
- }
- }
+ for (size_t i = 0; i < curr.size(); i++) {
+ const wp<IBinder>& displayToken = curr.keyAt(i);
+ if (draw.indexOfKey(displayToken) < 0) {
+ processDisplayAdded(displayToken, curr[i]);
}
}
}
@@ -2769,6 +2800,19 @@
void SurfaceFlinger::updateInputWindowInfo() {
std::vector<InputWindowInfo> inputHandles;
+ // We use a simple caching algorithm here. mInputDirty begins as true,
+ // after we call setInputWindows we set it to false, so
+ // in the future we wont call it again.. We set input dirty to true again
+ // when any layer that hasInput() has a transaction performed on it
+ // or when any parent or relative parent of such a layer has a transaction
+ // performed on it. Not all of these transactions will really result in
+ // input changes but all input changes will spring from these transactions
+ // so the cache is safe but not optimal. It seems like it might be annoyingly
+ // costly to cache and comapre the actual InputWindowHandle vector though.
+ if (!mInputDirty && !mInputWindowCommands.syncInputWindows) {
+ return;
+ }
+
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (layer->hasInput()) {
// When calculating the screen bounds we ignore the transparent region since it may
@@ -2780,10 +2824,12 @@
mInputFlinger->setInputWindows(inputHandles,
mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
: nullptr);
+
+ mInputDirty = false;
}
void SurfaceFlinger::commitInputWindowCommands() {
- mInputWindowCommands = mPendingInputWindowCommands;
+ mInputWindowCommands.merge(mPendingInputWindowCommands);
mPendingInputWindowCommands.clear();
}
@@ -3058,9 +3104,9 @@
parent = parentLayer;
}
- if (mNumLayers >= MAX_LAYERS) {
+ if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) {
ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
- MAX_LAYERS);
+ ISurfaceComposer::MAX_LAYERS);
return NO_MEMORY;
}
@@ -3550,7 +3596,7 @@
if (layer->setCornerRadius(s.cornerRadius))
flags |= eTraversalNeeded;
}
- if (what & layer_state_t::eBackgroundBlurRadiusChanged) {
+ if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs) {
if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eLayerStackChanged) {
@@ -3720,10 +3766,6 @@
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
uint32_t flags = 0;
- if (!inputWindowCommands.transferTouchFocusCommands.empty()) {
- flags |= eTraversalNeeded;
- }
-
if (inputWindowCommands.syncInputWindows) {
flags |= eTraversalNeeded;
}
@@ -4449,12 +4491,11 @@
result.append("\n");
}
-LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
- Mutex::Autolock _l(mStateLock);
- const auto device = getDefaultDisplayDeviceLocked();
+LayersProto SurfaceFlinger::dumpDrawingStateProto(
+ uint32_t traceFlags, const sp<const DisplayDevice>& displayDevice) const {
LayersProto layersProto;
for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
- layer->writeToProto(layersProto, traceFlags, device);
+ layer->writeToProto(layersProto, traceFlags, displayDevice);
}
return layersProto;
@@ -4486,7 +4527,10 @@
LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
LayersProto layersProto;
- postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
+ postMessageSync(new LambdaMessage([&]() {
+ const auto& displayDevice = getDefaultDisplayDeviceLocked();
+ layersProto = dumpDrawingStateProto(traceFlags, displayDevice);
+ }));
return layersProto;
}
@@ -5128,7 +5172,7 @@
n = data.readInt32();
if (n == 1 && !mRefreshRateOverlay) {
mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
- auto current = mRefreshRateConfigs->getCurrentRefreshRate();
+ auto& current = mRefreshRateConfigs->getCurrentRefreshRate();
mRefreshRateOverlay->changeRefreshRate(current);
} else if (n == 0) {
mRefreshRateOverlay.reset();
@@ -5177,7 +5221,7 @@
if (mRefreshRateOverlay) {
const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
const bool timerExpired = kernelTimerEnabled && expired;
- const auto& current = [this]() {
+ const auto& current = [this]() -> const RefreshRate& {
std::lock_guard<std::mutex> lock(mActiveConfigLock);
if (mDesiredActiveConfigChanged) {
return mRefreshRateConfigs->getRefreshRateFromConfigId(
@@ -5758,6 +5802,7 @@
Mutex::Autolock _l(mStateLock);
mPendingSyncInputWindows = false;
+
mTransactionCV.broadcast();
}
@@ -5857,7 +5902,7 @@
display->getActiveConfig(), vsyncPeriod);
auto configId = mScheduler->getPreferredConfigId();
- auto preferredRefreshRate = configId
+ auto& preferredRefreshRate = configId
? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId)
// NOTE: Choose the default config ID, if Scheduler doesn't have one in mind.
: mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 83f0131..44e18a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -42,6 +42,7 @@
#include <system/graphics.h>
#include <ui/FenceTime.h>
#include <ui/PixelFormat.h>
+#include <ui/Size.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -225,6 +226,11 @@
// FramebufferSurface
static int64_t maxFrameBufferAcquiredBuffers;
+ // Controls the maximum width and height in pixels that the graphics pipeline can support for
+ // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs.
+ static uint32_t maxGraphicsWidth;
+ static uint32_t maxGraphicsHeight;
+
// Indicate if a device has wide color gamut display. This is typically
// found on devices with wide color gamut (e.g. Display-P3) display.
static bool hasWideColorDisplay;
@@ -351,7 +357,6 @@
// every half hour.
enum { LOG_FRAME_STATS_PERIOD = 30*60*60 };
- static const size_t MAX_LAYERS = 4096;
static const int MAX_TRACING_MEMORY = 100 * 1024 * 1024; // 100MB
protected:
@@ -815,9 +820,14 @@
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
const DisplayDeviceState& state,
- const sp<compositionengine::DisplaySurface>& dispSurface,
+ const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer);
void processDisplayChangesLocked();
+ void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state);
+ void processDisplayRemoved(const wp<IBinder>& displayToken);
+ void processDisplayChanged(const wp<IBinder>& displayToken,
+ const DisplayDeviceState& currentState,
+ const DisplayDeviceState& drawingState);
void processDisplayHotplugEventsLocked();
void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected);
@@ -918,7 +928,8 @@
void dumpDisplayIdentificationData(std::string& result) const;
void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
void dumpWideColorInfo(std::string& result) const;
- LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL,
+ const sp<const DisplayDevice>& displayDevice = nullptr) const;
void dumpOffscreenLayersProto(LayersProto& layersProto,
uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
// Dumps state from HW Composer
@@ -976,7 +987,7 @@
// Can't be unordered_set because wp<> isn't hashable
std::set<wp<IBinder>> mGraphicBufferProducerList;
- size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
+ size_t mMaxGraphicBufferProducerListSize = ISurfaceComposer::MAX_LAYERS;
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved = false;
@@ -1049,8 +1060,10 @@
const std::shared_ptr<TimeStats> mTimeStats;
const std::unique_ptr<FrameTracer> mFrameTracer;
bool mUseHwcVirtualDisplays = false;
+ // If blurs should be enabled on this device.
+ bool mSupportsBlur = false;
// Disable blurs, for debugging
- bool mEnableBlurs = false;
+ std::atomic<bool> mDisableBlurs = false;
// If blurs are considered expensive and should require high GPU frequency.
bool mBlursAreExpensive = false;
std::atomic<uint32_t> mFrameMissedCount = 0;
@@ -1124,6 +1137,10 @@
// to linkToDeath
sp<IBinder> mWindowManager;
+ // We want to avoid multiple calls to BOOT_FINISHED as they come in on
+ // different threads without a lock and could trigger unsynchronized writes to
+ // to mWindowManager or mInputFlinger
+ std::atomic<bool> mBootFinished = false;
std::unique_ptr<dvr::VrFlinger> mVrFlinger;
std::atomic<bool> mVrFlingerRequestsDisplay = false;
@@ -1236,6 +1253,11 @@
// janky frames there are.
nsecs_t mMissedFrameJankStart = 0;
int32_t mMissedFrameJankCount = 0;
+
+ // See updateInputWindowInfo() for details
+ std::atomic<bool> mInputDirty = true;
+ void dirtyInput() { mInputDirty = true; }
+ bool inputDirty() { return mInputDirty; }
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index f3352a5..9d78702 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -70,6 +70,22 @@
defaultValue);
}
+int32_t max_graphics_width(int32_t defaultValue) {
+ auto temp = SurfaceFlingerProperties::max_graphics_width();
+ if (temp.has_value()) {
+ return *temp;
+ }
+ return defaultValue;
+}
+
+int32_t max_graphics_height(int32_t defaultValue) {
+ auto temp = SurfaceFlingerProperties::max_graphics_height();
+ if (temp.has_value()) {
+ return *temp;
+ }
+ return defaultValue;
+}
+
bool has_wide_color_display(bool defaultValue) {
auto temp = SurfaceFlingerProperties::has_wide_color_display();
if (temp.has_value()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 12c711a..c63adfe 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -37,6 +37,9 @@
int64_t max_frame_buffer_acquired_buffers(int64_t defaultValue);
+int32_t max_graphics_width(int32_t defaultValue);
+int32_t max_graphics_height(int32_t defaultValue);
+
bool has_wide_color_display(bool defaultValue);
bool running_without_sync_framework(bool defaultValue);
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 1f9d46c..5b3cd69 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -524,11 +524,11 @@
deletion->set_id(getLayerId(layer));
}
-void SurfaceInterceptor::addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer,
+void SurfaceInterceptor::addBufferUpdateLocked(Increment* increment, int32_t layerId,
uint32_t width, uint32_t height, uint64_t frameNumber)
{
BufferUpdate* update(increment->mutable_buffer_update());
- update->set_id(getLayerId(layer));
+ update->set_id(layerId);
update->set_w(width);
update->set_h(height);
update->set_frame_number(frameNumber);
@@ -644,15 +644,22 @@
addSurfaceDeletionLocked(createTraceIncrementLocked(), layer);
}
-void SurfaceInterceptor::saveBufferUpdate(const sp<const Layer>& layer, uint32_t width,
+/**
+ * Here we pass the layer by ID instead of by sp<> since this is called without
+ * holding the state-lock from a Binder thread. If we required the caller
+ * to pass 'this' by sp<> the temporary sp<> constructed could end up
+ * being the last reference and we might accidentally destroy the Layer
+ * from this binder thread.
+ */
+void SurfaceInterceptor::saveBufferUpdate(int32_t layerId, uint32_t width,
uint32_t height, uint64_t frameNumber)
{
- if (!mEnabled || layer == nullptr) {
+ if (!mEnabled) {
return;
}
ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addBufferUpdateLocked(createTraceIncrementLocked(), layer, width, height, frameNumber);
+ addBufferUpdateLocked(createTraceIncrementLocked(), layerId, width, height, frameNumber);
}
void SurfaceInterceptor::saveVSyncEvent(nsecs_t timestamp) {
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index a665f62..896bdcc 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -67,7 +67,7 @@
// Intercept surface data
virtual void saveSurfaceCreation(const sp<const Layer>& layer) = 0;
virtual void saveSurfaceDeletion(const sp<const Layer>& layer) = 0;
- virtual void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
+ virtual void saveBufferUpdate(int32_t layerId, uint32_t width, uint32_t height,
uint64_t frameNumber) = 0;
// Intercept display data
@@ -102,7 +102,7 @@
// Intercept surface data
void saveSurfaceCreation(const sp<const Layer>& layer) override;
void saveSurfaceDeletion(const sp<const Layer>& layer) override;
- void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
+ void saveBufferUpdate(int32_t layerId, uint32_t width, uint32_t height,
uint64_t frameNumber) override;
// Intercept display data
@@ -130,7 +130,7 @@
Increment* createTraceIncrementLocked();
void addSurfaceCreationLocked(Increment* increment, const sp<const Layer>& layer);
void addSurfaceDeletionLocked(Increment* increment, const sp<const Layer>& layer);
- void addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width,
+ void addBufferUpdateLocked(Increment* increment, int32_t layerId, uint32_t width,
uint32_t height, uint64_t frameNumber);
void addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp);
void addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info);
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index c5556ec..20c8d7a 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -45,19 +45,21 @@
}
void SurfaceTracing::addFirstEntry() {
+ const auto displayDevice = mFlinger.getDefaultDisplayDevice();
LayersTraceProto entry;
{
std::scoped_lock lock(mSfLock);
- entry = traceLayersLocked("tracing.enable");
+ entry = traceLayersLocked("tracing.enable", displayDevice);
}
addTraceToBuffer(entry);
}
LayersTraceProto SurfaceTracing::traceWhenNotified() {
+ const auto displayDevice = mFlinger.getDefaultDisplayDevice();
std::unique_lock<std::mutex> lock(mSfLock);
mCanStartTrace.wait(lock);
android::base::ScopedLockAssertion assumeLock(mSfLock);
- LayersTraceProto entry = traceLayersLocked(mWhere);
+ LayersTraceProto entry = traceLayersLocked(mWhere, displayDevice);
lock.unlock();
return entry;
}
@@ -160,13 +162,14 @@
mTraceFlags = flags;
}
-LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
+LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where,
+ const sp<const DisplayDevice>& displayDevice) {
ATRACE_CALL();
LayersTraceProto entry;
entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry.set_where(where);
- LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
+ LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags, displayDevice));
mFlinger.dumpOffscreenLayersProto(layers);
entry.mutable_layers()->Swap(&layers);
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 3c24881..4b9f777 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -16,17 +16,19 @@
#pragma once
+#include <android-base/thread_annotations.h>
#include <layerproto/LayerProtoHeader.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
-#include <android-base/thread_annotations.h>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
+#include "DisplayDevice.h"
+
using namespace android::surfaceflinger;
namespace android {
@@ -85,13 +87,15 @@
void mainLoop();
void addFirstEntry();
LayersTraceProto traceWhenNotified();
- LayersTraceProto traceLayersLocked(const char* where) REQUIRES(mSfLock);
+ LayersTraceProto traceLayersLocked(const char* where,
+ const sp<const DisplayDevice>& displayDevice)
+ REQUIRES(mSfLock);
// Returns true if trace is enabled.
bool addTraceToBuffer(LayersTraceProto& entry);
void writeProtoFileLocked() REQUIRES(mTraceLock);
- const SurfaceFlinger& mFlinger;
+ SurfaceFlinger& mFlinger;
status_t mLastErr = NO_ERROR;
std::thread mThread;
std::condition_variable mCanStartTrace;
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 155f718..cfc301b 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -67,6 +67,26 @@
prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
}
+# Controls the maximum width in pixels that the graphics pipeline can support for GPU fallback
+# composition. For example, 8k displays with 4k GPUs, or 4k displays with 2k GPUs.
+prop {
+ api_name: "max_graphics_width"
+ type: Integer
+ scope: System
+ access: Readonly
+ prop_name: "ro.surface_flinger.max_graphics_width"
+}
+
+# Controls the maximum height in pixels that the graphics pipeline can support for GPU fallback
+# composition. For example, 8k displays with 4k GPUs, or 4k displays with 2k GPUs.
+prop {
+ api_name: "max_graphics_height"
+ type: Integer
+ scope: System
+ access: Readonly
+ prop_name: "ro.surface_flinger.max_graphics_height"
+}
+
# hasWideColorDisplay indicates that the device has
# or can support a wide-color display, e.g. color space
# greater than sRGB. Typical display may have same
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index e62c127..ba60a7d 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -62,6 +62,16 @@
prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
}
prop {
+ api_name: "max_graphics_height"
+ type: Integer
+ prop_name: "ro.surface_flinger.max_graphics_height"
+ }
+ prop {
+ api_name: "max_graphics_width"
+ type: Integer
+ prop_name: "ro.surface_flinger.max_graphics_width"
+ }
+ prop {
api_name: "max_virtual_display_dimension"
type: Long
prop_name: "ro.surface_flinger.max_virtual_display_dimension"
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index a023367..c2ddfce 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#include <functional>
+#include <string_view>
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -124,6 +127,10 @@
return DisplayIdentificationData(bytes, bytes + N - 1);
}
+uint32_t hash(const char* str) {
+ return static_cast<uint32_t>(std::hash<std::string_view>()(str));
+}
+
} // namespace
const DisplayIdentificationData& getInternalEdid() {
@@ -173,7 +180,8 @@
EXPECT_EQ(0x4ca3u, edid->manufacturerId);
EXPECT_STREQ("SEC", edid->pnpId.data());
// ASCII text should be used as fallback if display name and serial number are missing.
- EXPECT_EQ("121AT11-801", edid->displayName);
+ EXPECT_EQ(hash("121AT11-801"), edid->modelHash);
+ EXPECT_TRUE(edid->displayName.empty());
EXPECT_EQ(12610, edid->productId);
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
@@ -182,6 +190,7 @@
ASSERT_TRUE(edid);
EXPECT_EQ(0x22f0u, edid->manufacturerId);
EXPECT_STREQ("HWP", edid->pnpId.data());
+ EXPECT_EQ(hash("HP ZR30w"), edid->modelHash);
EXPECT_EQ("HP ZR30w", edid->displayName);
EXPECT_EQ(10348, edid->productId);
EXPECT_EQ(22, edid->manufactureOrModelYear);
@@ -191,6 +200,7 @@
ASSERT_TRUE(edid);
EXPECT_EQ(0x4c2du, edid->manufacturerId);
EXPECT_STREQ("SAM", edid->pnpId.data());
+ EXPECT_EQ(hash("SAMSUNG"), edid->modelHash);
EXPECT_EQ("SAMSUNG", edid->displayName);
EXPECT_EQ(2302, edid->productId);
EXPECT_EQ(21, edid->manufactureOrModelYear);
@@ -200,6 +210,7 @@
ASSERT_TRUE(edid);
EXPECT_EQ(13481, edid->manufacturerId);
EXPECT_STREQ("MEI", edid->pnpId.data());
+ EXPECT_EQ(hash("Panasonic-TV"), edid->modelHash);
EXPECT_EQ("Panasonic-TV", edid->displayName);
EXPECT_EQ(41622, edid->productId);
EXPECT_EQ(29, edid->manufactureOrModelYear);
@@ -209,6 +220,7 @@
ASSERT_TRUE(edid);
EXPECT_EQ(8355, edid->manufacturerId);
EXPECT_STREQ("HEC", edid->pnpId.data());
+ EXPECT_EQ(hash("Hisense"), edid->modelHash);
EXPECT_EQ("Hisense", edid->displayName);
EXPECT_EQ(0, edid->productId);
EXPECT_EQ(29, edid->manufactureOrModelYear);
@@ -218,6 +230,7 @@
ASSERT_TRUE(edid);
EXPECT_EQ(3724, edid->manufacturerId);
EXPECT_STREQ("CTL", edid->pnpId.data());
+ EXPECT_EQ(hash("LP2361"), edid->modelHash);
EXPECT_EQ("LP2361", edid->displayName);
EXPECT_EQ(9373, edid->productId);
EXPECT_EQ(23, edid->manufactureOrModelYear);
@@ -234,13 +247,15 @@
auto edid = parseEdid(data);
ASSERT_TRUE(edid);
// Serial number should be used as fallback if display name is invalid.
- EXPECT_EQ("CN4202137Q", edid->displayName);
+ const auto modelHash = hash("CN4202137Q");
+ EXPECT_EQ(modelHash, edid->modelHash);
+ EXPECT_TRUE(edid->displayName.empty());
// Parsing should succeed even if EDID is truncated.
data.pop_back();
edid = parseEdid(data);
ASSERT_TRUE(edid);
- EXPECT_EQ("CN4202137Q", edid->displayName);
+ EXPECT_EQ(modelHash, edid->modelHash);
}
TEST(DisplayIdentificationTest, getPnpId) {
@@ -278,7 +293,7 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("121AT11-801", info.name.data());
+ EXPECT_STREQ("", info.name.data());
EXPECT_STREQ("SEC", info.manufacturerPnpId.data());
EXPECT_STREQ("12610", info.productId.data());
ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index e7e7f66..dd04076 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -21,6 +21,7 @@
#include <log/log.h>
#include <thread>
+#include "../../Scheduler/RefreshRateConfigs.h"
#include "DisplayHardware/HWC2.h"
#include "Scheduler/RefreshRateConfigs.h"
@@ -93,8 +94,8 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- const auto minRate = refreshRateConfigs->getMinRefreshRate();
- const auto performanceRate = refreshRateConfigs->getMaxRefreshRate();
+ const auto& minRate = refreshRateConfigs->getMinRefreshRate();
+ const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
ASSERT_EQ(expectedDefaultConfig, minRate);
@@ -102,8 +103,8 @@
90};
ASSERT_EQ(expectedPerformanceConfig, performanceRate);
- const auto minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy();
ASSERT_EQ(minRateByPolicy, minRate);
ASSERT_EQ(performanceRateByPolicy, performanceRate);
}
@@ -115,10 +116,10 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRate = refreshRateConfigs->getMaxRefreshRate();
- const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
+ const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
ASSERT_EQ(expectedDefaultConfig, minRate);
@@ -128,8 +129,8 @@
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90, nullptr), 0);
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
- const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
- const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps",
90};
@@ -145,8 +146,8 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
- auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
+ auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy();
RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
ASSERT_EQ(expectedDefaultConfig, minRate);
@@ -156,8 +157,8 @@
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0);
- auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
- auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+ auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
ASSERT_EQ(expectedDefaultConfig, minRate60);
ASSERT_EQ(expectedDefaultConfig, performanceRate60);
}
@@ -169,19 +170,19 @@
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
{
- auto current = refreshRateConfigs->getCurrentRefreshRate();
+ auto& current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_60);
}
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
{
- auto current = refreshRateConfigs->getCurrentRefreshRate();
+ auto& current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_90);
}
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0);
{
- auto current = refreshRateConfigs->getCurrentRefreshRate();
+ auto& current = refreshRateConfigs->getCurrentRefreshRate();
EXPECT_EQ(current.configId, HWC_CONFIG_ID_90);
}
}
@@ -248,6 +249,7 @@
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
@@ -263,16 +265,17 @@
auto layers = std::vector<LayerRequirement>{};
EXPECT_EQ(expected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
- false));
+ false, &ignored));
// Current refresh rate can always be changed.
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60);
EXPECT_EQ(expected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
- false));
+ false, &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -288,134 +291,163 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.name = "";
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_72_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
@@ -432,35 +464,43 @@
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -486,24 +526,28 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_DifferentTypes) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -531,7 +575,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -540,7 +585,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -549,7 +595,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -558,7 +605,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -567,7 +615,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -576,7 +625,8 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
@@ -585,7 +635,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -594,7 +645,8 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -603,10 +655,12 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}};
@@ -621,35 +675,43 @@
lr.vote = LayerVoteType::Min;
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -669,57 +731,71 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
lr.desiredRefreshRate = 24.0f;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
@@ -739,48 +815,56 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 15.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 30.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -798,7 +882,8 @@
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false);
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored);
printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
EXPECT_EQ(expected60Config, refreshRate);
}
@@ -833,6 +918,7 @@
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -852,21 +938,24 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, testInPolicy) {
@@ -880,6 +969,7 @@
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -897,13 +987,15 @@
for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false);
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored);
printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
EXPECT_EQ(expected90Config, refreshRate);
}
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -925,7 +1017,8 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -934,7 +1027,8 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -942,7 +1036,8 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -951,7 +1046,8 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -959,10 +1055,12 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false));
+ refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
+ &ignored));
}
TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) {
+ bool ignored;
std::vector<RefreshRateConfigs::InputConfig> configs{
{{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
{HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
@@ -982,28 +1080,32 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false));
+ EXPECT_EQ(expected60Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, true));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, true));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
// The other layer starts to provide buffers
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1012,7 +1114,108 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers, false));
+ EXPECT_EQ(expected90Config,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
+}
+
+TEST_F(RefreshRateConfigsTest, touchConsidered) {
+ bool touchConsidered;
+ std::vector<RefreshRateConfigs::InputConfig> configs{
+ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
+ {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ refreshRateConfigs->getRefreshRateForContentV2({}, false, &touchConsidered);
+ EXPECT_EQ(false, touchConsidered);
+
+ refreshRateConfigs->getRefreshRateForContentV2({}, true, &touchConsidered);
+ EXPECT_EQ(true, touchConsidered);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+ LayerRequirement{.weight = 1.0f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(true, touchConsidered);
+
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(false, touchConsidered);
+
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(true, touchConsidered);
+
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.desiredRefreshRate = 60.0f;
+ lr1.name = "60Hz ExplicitExactrMultiple";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "NoVote";
+ refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ EXPECT_EQ(false, touchConsidered);
+}
+
+TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) {
+ bool ignored;
+ std::vector<RefreshRateConfigs::InputConfig> configs{
+ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
+ {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
+ {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
+ {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
+
+ auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/
+ HWC_CONFIG_ID_60);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ // Prepare a table with the vote and the expected refresh rate
+ const std::vector<std::pair<float, float>> testCases = {
+ {130, 120}, {120, 120}, {119, 120}, {110, 120},
+
+ {100, 90}, {90, 90}, {89, 90},
+
+ {80, 72}, {73, 72}, {72, 72}, {71, 72}, {70, 72},
+
+ {65, 60}, {60, 60}, {59, 60}, {58, 60},
+
+ {55, 90}, {50, 90}, {45, 90},
+
+ {42, 120}, {40, 120}, {39, 120},
+
+ {37, 72}, {36, 72}, {35, 72},
+
+ {30, 60},
+ };
+
+ for (const auto& test : testCases) {
+ lr.vote = LayerVoteType::ExplicitDefault;
+ lr.desiredRefreshRate = test.first;
+
+ std::stringstream ss;
+ ss << "ExplicitDefault " << test.first << " fps";
+ lr.name = ss.str();
+
+ const auto& refreshRate =
+ refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored);
+ EXPECT_FLOAT_EQ(refreshRate.fps, test.second)
+ << "Expecting " << test.first << "fps => " << test.second << "Hz";
+ }
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h
index 458b2f3..5beee1c 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h
@@ -39,7 +39,7 @@
const Vector<DisplayState>&, uint32_t));
MOCK_METHOD1(saveSurfaceCreation, void(const sp<const Layer>&));
MOCK_METHOD1(saveSurfaceDeletion, void(const sp<const Layer>&));
- MOCK_METHOD4(saveBufferUpdate, void(const sp<const Layer>&, uint32_t, uint32_t, uint64_t));
+ MOCK_METHOD4(saveBufferUpdate, void(int32_t, uint32_t, uint32_t, uint64_t));
MOCK_METHOD1(saveDisplayCreation, void(const DisplayDeviceState&));
MOCK_METHOD1(saveDisplayDeletion, void(int32_t));
MOCK_METHOD2(savePowerModeUpdate, void(int32_t, int32_t));