Merge "Prevent processing touch after receiving an invalid tracking id" into sc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 25e6dc9..4eb601d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -176,6 +176,7 @@
#define LINKERCONFIG_DIR "/linkerconfig"
#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
+#define CGROUPFS_DIR "/sys/fs/cgroup"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -1785,6 +1786,9 @@
// Add linker configuration directory
ds.AddDir(LINKERCONFIG_DIR, true);
+ /* Dump cgroupfs */
+ ds.AddDir(CGROUPFS_DIR, true);
+
if (ds.dump_pool_) {
WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
} else {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 59311a0..74be7ce 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -342,8 +342,7 @@
// If the initial top-level restorecon above changed the label, then go
// back and restorecon everything recursively
- // TODO(b/190567190, b/188141923) Remove recursive fixup of com.google.android.gsf.
- if (strcmp(before, after) || (path.find("com.google.android.gsf") != std::string::npos)) {
+ if (strcmp(before, after)) {
if (existing) {
LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at "
<< path << "; running recursive restorecon";
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 15f0c5b..cd5c36f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -492,6 +492,14 @@
std::to_string(min_new_methods_percent_change));
}
+ // On-device signing related. odsign sets the system property odsign.verification.success if
+ // AOT artifacts have the expected signatures.
+ const bool trust_art_apex_data_files =
+ ::android::base::GetBoolProperty("odsign.verification.success", false);
+ if (!trust_art_apex_data_files) {
+ AddRuntimeArg("-Xdeny-art-apex-data-files");
+ }
+
// Do not add after dex2oat_flags, they should override others for debugging.
PrepareArgs(profman_bin);
}
@@ -1231,6 +1239,14 @@
}
}
+ // On-device signing related. odsign sets the system property odsign.verification.success if
+ // AOT artifacts have the expected signatures.
+ const bool trust_art_apex_data_files =
+ ::android::base::GetBoolProperty("odsign.verification.success", false);
+ if (!trust_art_apex_data_files) {
+ AddRuntimeArg("-Xdeny-art-apex-data-files");
+ }
+
PrepareArgs(dexoptanalyzer_bin);
}
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index e847626..b661684 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -283,6 +283,13 @@
}
}
+ // On-device signing related. odsign sets the system property odsign.verification.success if
+ // AOT artifacts have the expected signatures.
+ const bool trust_art_apex_data_files = GetBoolProperty("odsign.verification.success", false);
+ if (!trust_art_apex_data_files) {
+ AddRuntimeArg("-Xdeny-art-apex-data-files");
+ }
+
if (target_sdk_version != 0) {
AddRuntimeArg(StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version));
}
diff --git a/include/input/Input.h b/include/input/Input.h
index e8678d2..6f2d716 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -43,6 +43,13 @@
* Additional private constants not defined in ndk/ui/input.h.
*/
enum {
+#ifdef __linux__
+ /* This event was generated or modified by accessibility service. */
+ AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
+ android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, // 0x800,
+#else
+ AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800,
+#endif
/* Signifies that the key is being predispatched */
AKEY_EVENT_FLAG_PREDISPATCH = 0x20000000,
@@ -81,6 +88,16 @@
*/
AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE = 0x40,
+#ifdef __linux__
+ /**
+ * This event was generated or modified by accessibility service.
+ */
+ AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
+ android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, // 0x800,
+#else
+ AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
+#endif
+
/* Motion event is inconsistent with previously sent motion events. */
AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
};
@@ -89,14 +106,15 @@
* Allowed VerifiedKeyEvent flags. All other flags from KeyEvent do not get verified.
* These values must be kept in sync with VerifiedKeyEvent.java
*/
-constexpr int32_t VERIFIED_KEY_EVENT_FLAGS = AKEY_EVENT_FLAG_CANCELED;
+constexpr int32_t VERIFIED_KEY_EVENT_FLAGS =
+ AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
/**
* Allowed VerifiedMotionEventFlags. All other flags from MotionEvent do not get verified.
* These values must be kept in sync with VerifiedMotionEvent.java
*/
-constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS =
- AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED |
+ AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED | AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
/**
* This flag indicates that the point up event has been canceled.
@@ -222,16 +240,14 @@
POLICY_FLAG_GESTURE = 0x00000008,
POLICY_FLAG_RAW_MASK = 0x0000ffff,
-#ifdef __linux__
- POLICY_FLAG_INPUTFILTER_TRUSTED = android::os::IInputConstants::POLICY_FLAG_INPUTFILTER_TRUSTED,
+#ifdef __linux__
POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY =
android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
#else
- POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000,
-
POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000,
#endif
+
/* These flags are set by the input dispatcher. */
// Indicates that the input event was injected.
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 1955104..7f0324a 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -318,8 +318,6 @@
const std::string& name, InputDeviceConfigurationFileType type);
enum ReservedInputDeviceId : int32_t {
- // Device id assigned to input events generated inside accessibility service
- ACCESSIBILITY_DEVICE_ID = -2,
// Device id of a special "virtual" keyboard that is always present.
VIRTUAL_KEYBOARD_ID = -1,
// Device id of the "built-in" keyboard if there is one.
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index 6165911..f66993f 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -40,9 +40,9 @@
void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
- bool tryUnregister();
+ bool tryUnregisterLocked();
- void reRegister();
+ void reRegisterLocked();
protected:
Status onClients(const sp<IBinder>& service, bool clients) override;
@@ -59,6 +59,9 @@
bool registered = true;
};
+ bool registerServiceLocked(const sp<IBinder>& service, const std::string& name,
+ bool allowIsolated, int dumpFlags);
+
/**
* Looks up a service guaranteed to be registered (service from onClients).
*/
@@ -68,7 +71,7 @@
* Unregisters all services that we can. If we can't unregister all, re-register other
* services.
*/
- void tryShutdown();
+ void tryShutdownLocked();
/**
* Try to shutdown the process, unless:
@@ -76,7 +79,10 @@
* - The active services count callback returns 'true', or
* - Some services have clients.
*/
- void maybeTryShutdown();
+ void maybeTryShutdownLocked();
+
+ // for below
+ std::mutex mMutex;
// count of services with clients
size_t mNumConnectedServices;
@@ -117,6 +123,13 @@
bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
bool allowIsolated, int dumpFlags) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return registerServiceLocked(service, name, allowIsolated, dumpFlags);
+}
+
+bool ClientCounterCallbackImpl::registerServiceLocked(const sp<IBinder>& service,
+ const std::string& name, bool allowIsolated,
+ int dumpFlags) {
auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
bool reRegister = mRegisteredServices.count(name) > 0;
@@ -164,14 +177,15 @@
}
void ClientCounterCallbackImpl::forcePersist(bool persist) {
+ std::lock_guard<std::mutex> lock(mMutex);
mForcePersist = persist;
if (!mForcePersist) {
// Attempt a shutdown in case the number of clients hit 0 while the flag was on
- maybeTryShutdown();
+ maybeTryShutdownLocked();
}
}
-bool ClientCounterCallbackImpl::tryUnregister() {
+bool ClientCounterCallbackImpl::tryUnregisterLocked() {
auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
for (auto& [name, entry] : mRegisteredServices) {
@@ -187,15 +201,14 @@
return true;
}
-void ClientCounterCallbackImpl::reRegister() {
+void ClientCounterCallbackImpl::reRegisterLocked() {
for (auto& [name, entry] : mRegisteredServices) {
// re-register entry if not already registered
if (entry.registered) {
continue;
}
- if (!registerService(entry.service, name, entry.allowIsolated,
- entry.dumpFlags)) {
+ if (!registerServiceLocked(entry.service, name, entry.allowIsolated, entry.dumpFlags)) {
// Must restart. Otherwise, clients will never be able to get a hold of this service.
LOG_ALWAYS_FATAL("Bad state: could not re-register services");
}
@@ -204,7 +217,7 @@
}
}
-void ClientCounterCallbackImpl::maybeTryShutdown() {
+void ClientCounterCallbackImpl::maybeTryShutdownLocked() {
if (mForcePersist) {
ALOGI("Shutdown prevented by forcePersist override flag.");
return;
@@ -223,15 +236,12 @@
// client count change event, try to shutdown the process if its services
// have no clients.
if (!handledInCallback && mNumConnectedServices == 0) {
- tryShutdown();
+ tryShutdownLocked();
}
}
-/**
- * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
- * invocations could occur on different threads however.
- */
Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
+ std::lock_guard<std::mutex> lock(mMutex);
auto & [name, registered] = *assertRegisteredService(service);
if (registered.clients == clients) {
LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
@@ -252,23 +262,24 @@
ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
- maybeTryShutdown();
+ maybeTryShutdownLocked();
return Status::ok();
}
- void ClientCounterCallbackImpl::tryShutdown() {
- ALOGI("Trying to shut down the service. No clients in use for any service in process.");
+void ClientCounterCallbackImpl::tryShutdownLocked() {
+ ALOGI("Trying to shut down the service. No clients in use for any service in process.");
- if (tryUnregister()) {
- ALOGI("Unregistered all clients and exiting");
- exit(EXIT_SUCCESS);
- }
+ if (tryUnregisterLocked()) {
+ ALOGI("Unregistered all clients and exiting");
+ exit(EXIT_SUCCESS);
+ }
- reRegister();
+ reRegisterLocked();
}
void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
activeServicesCallback) {
+ std::lock_guard<std::mutex> lock(mMutex);
mActiveServicesCallback = activeServicesCallback;
}
@@ -291,11 +302,15 @@
}
bool ClientCounterCallback::tryUnregister() {
- return mImpl->tryUnregister();
+ // see comments in header, this should only be called from the active
+ // services callback, see also b/191781736
+ return mImpl->tryUnregisterLocked();
}
void ClientCounterCallback::reRegister() {
- mImpl->reRegister();
+ // see comments in header, this should only be called from the active
+ // services callback, see also b/191781736
+ mImpl->reRegisterLocked();
}
} // namespace internal
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index f3ba830..2e22b84 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -79,9 +79,10 @@
*/
void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
- /**
+ /**
* Try to unregister all services previously registered with 'registerService'.
- * Returns 'true' if successful.
+ * Returns 'true' if successful. This should only be called within the callback registered by
+ * setActiveServicesCallback.
*/
bool tryUnregister();
diff --git a/libs/binder/libbinder.arm32.map b/libs/binder/libbinder.arm32.map
index 64fdd91..c8aebb3 100644
--- a/libs/binder/libbinder.arm32.map
+++ b/libs/binder/libbinder.arm32.map
@@ -389,15 +389,6 @@
_ZN7android6binder8internal21ClientCounterCallback25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
_ZN7android6binder8internal21ClientCounterCallbackC1Ev;
_ZN7android6binder8internal21ClientCounterCallbackC2Ev;
- _ZN7android6binder8internal25ClientCounterCallbackImpl10reRegisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl11tryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl12forcePersistEb;
- _ZN7android6binder8internal25ClientCounterCallbackImpl13tryUnregisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl15registerServiceERKNS_2spINS_7IBinderEEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEbi;
- _ZN7android6binder8internal25ClientCounterCallbackImpl16maybeTryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl23assertRegisteredServiceERKNS_2spINS_7IBinderEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl9onClientsERKNS_2spINS_7IBinderEEEb;
_ZN7android6Parcel10appendFromEPKS0_jj;
_ZN7android6Parcel10markForRpcERKNS_2spINS_10RpcSessionEEE;
_ZN7android6Parcel10writeFloatEf;
@@ -1076,7 +1067,6 @@
_ZNKSt3__16__treeINS_12__value_typeIN7android8String16ENS_6vectorIxNS_9allocatorIxEEEEEENS_19__map_value_compareIS3_S8_NS_4lessIS3_EELb1EEENS5_IS8_EEE4findIS3_EENS_21__tree_const_iteratorIS8_PNS_11__tree_nodeIS8_PvEEiEERKT_;
_ZNKSt3__16__treeINS_12__value_typeIN7android8String16ES3_EENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE4findIS3_EENS_21__tree_const_iteratorIS4_PNS_11__tree_nodeIS4_PvEEiEERKT_;
_ZNKSt3__16__treeINS_12__value_typeIN7android8String16ExEENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE4findIS3_EENS_21__tree_const_iteratorIS4_PNS_11__tree_nodeIS4_PvEEiEERKT_;
- _ZNKSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE14__count_uniqueIS7_EEjRKT_;
_ZNSt3__111__sift_downIRNS_4lessIN7android8RpcState10BinderNode9AsyncTodoEEENS_11__wrap_iterIPS5_EEEEvT0_SB_T_NS_15iterator_traitsISB_E15difference_typeESB_;
_ZNSt3__111unique_lockINS_5mutexEE6unlockEv;
_ZNSt3__112__hash_tableINS_17__hash_value_typeIijEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE14__erase_uniqueIiEEjRKT_;
@@ -1223,9 +1213,6 @@
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ExEENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE4findIS3_EENS_15__tree_iteratorIS4_PNS_11__tree_nodeIS4_PvEEiEERKT_;
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ExEENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
_ZNSt3__16__treeINS_12__value_typeINS_11__thread_idENS_6threadEEENS_19__map_value_compareIS2_S4_NS_4lessIS2_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE12__find_equalIS7_EERPNS_16__tree_node_baseIPvEERPNS_15__tree_end_nodeISO_EERKT_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE25__emplace_unique_key_argsIS7_JRKNS_21piecewise_construct_tENS_5tupleIJRKS7_EEENSO_IJEEEEEENS_4pairINS_15__tree_iteratorISD_PNS_11__tree_nodeISD_PvEEiEEbEERKT_DpOT0_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE7destroyEPNS_11__tree_nodeISD_PvEE;
_ZNSt3__16vectorIaNS_9allocatorIaEEE6insertIPKaEENS_9enable_ifIXaasr21__is_forward_iteratorIT_EE5valuesr16is_constructibleIaNS_15iterator_traitsIS8_E9referenceEEE5valueENS_11__wrap_iterIPaEEE4typeENSC_IS6_EES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb0ELj0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb1ELj0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
@@ -1353,12 +1340,6 @@
_ZTCN7android2os17BpServiceCallbackE0_NS_10IInterfaceE;
_ZTCN7android2os17BpServiceCallbackE0_NS_11BpInterfaceINS0_16IServiceCallbackEEE;
_ZTCN7android2os17BpServiceCallbackE4_NS_9BpRefBaseE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_10IInterfaceE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_11BnInterfaceINS_2os15IClientCallbackEEE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os15IClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os16BnClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE4_NS_7BBinderE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE4_NS_7IBinderE;
_ZTCN7android7BBinderE0_NS_7IBinderE;
_ZTCN7android7content2pm21IPackageManagerNativeE0_NS_10IInterfaceE;
_ZTCN7android7content2pm22BnPackageManagerNativeE0_NS_10IInterfaceE;
@@ -1447,7 +1428,6 @@
_ZTTN7android2os16IServiceCallbackE;
_ZTTN7android2os17BnServiceCallbackE;
_ZTTN7android2os17BpServiceCallbackE;
- _ZTTN7android6binder8internal25ClientCounterCallbackImplE;
_ZTTN7android7BBinderE;
_ZTTN7android7content2pm21IPackageManagerNativeE;
_ZTTN7android7content2pm22BnPackageManagerNativeE;
@@ -1581,7 +1561,6 @@
_ZTVN7android2os17BpServiceCallbackE;
_ZTVN7android2os17PersistableBundleE;
_ZTVN7android2os20ParcelFileDescriptorE;
- _ZTVN7android6binder8internal25ClientCounterCallbackImplE;
_ZTVN7android6VectorIiEE;
_ZTVN7android6VectorINS_12ProcessState12handle_entryEEE;
_ZTVN7android6VectorINS_2spINS_18BufferedTextOutput11BufferStateEEEEE;
diff --git a/libs/binder/libbinder.arm32.vendor.map b/libs/binder/libbinder.arm32.vendor.map
index 8d5a323..2aa65de 100644
--- a/libs/binder/libbinder.arm32.vendor.map
+++ b/libs/binder/libbinder.arm32.vendor.map
@@ -359,15 +359,6 @@
_ZN7android6binder8internal21ClientCounterCallback25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
_ZN7android6binder8internal21ClientCounterCallbackC1Ev;
_ZN7android6binder8internal21ClientCounterCallbackC2Ev;
- _ZN7android6binder8internal25ClientCounterCallbackImpl10reRegisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl11tryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl12forcePersistEb;
- _ZN7android6binder8internal25ClientCounterCallbackImpl13tryUnregisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl15registerServiceERKNS_2spINS_7IBinderEEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEbi;
- _ZN7android6binder8internal25ClientCounterCallbackImpl16maybeTryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl23assertRegisteredServiceERKNS_2spINS_7IBinderEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl9onClientsERKNS_2spINS_7IBinderEEEb;
_ZN7android6Parcel10appendFromEPKS0_jj;
_ZN7android6Parcel10markForRpcERKNS_2spINS_10RpcSessionEEE;
_ZN7android6Parcel10writeFloatEf;
@@ -1022,7 +1013,6 @@
_ZNKSt3__16__treeINS_12__value_typeIN7android8String16ENS_6vectorIxNS_9allocatorIxEEEEEENS_19__map_value_compareIS3_S8_NS_4lessIS3_EELb1EEENS5_IS8_EEE4findIS3_EENS_21__tree_const_iteratorIS8_PNS_11__tree_nodeIS8_PvEEiEERKT_;
_ZNKSt3__16__treeINS_12__value_typeIN7android8String16ES3_EENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE4findIS3_EENS_21__tree_const_iteratorIS4_PNS_11__tree_nodeIS4_PvEEiEERKT_;
_ZNKSt3__16__treeINS_12__value_typeIN7android8String16ExEENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE4findIS3_EENS_21__tree_const_iteratorIS4_PNS_11__tree_nodeIS4_PvEEiEERKT_;
- _ZNKSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE14__count_uniqueIS7_EEjRKT_;
_ZNSt3__111__sift_downIRNS_4lessIN7android8RpcState10BinderNode9AsyncTodoEEENS_11__wrap_iterIPS5_EEEEvT0_SB_T_NS_15iterator_traitsISB_E15difference_typeESB_;
_ZNSt3__111unique_lockINS_5mutexEE6unlockEv;
_ZNSt3__112__hash_tableINS_17__hash_value_typeIijEENS_22__unordered_map_hasherIiS2_NS_4hashIiEELb1EEENS_21__unordered_map_equalIiS2_NS_8equal_toIiEELb1EEENS_9allocatorIS2_EEE14__erase_uniqueIiEEjRKT_;
@@ -1169,9 +1159,6 @@
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ExEENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE4findIS3_EENS_15__tree_iteratorIS4_PNS_11__tree_nodeIS4_PvEEiEERKT_;
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ExEENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
_ZNSt3__16__treeINS_12__value_typeINS_11__thread_idENS_6threadEEENS_19__map_value_compareIS2_S4_NS_4lessIS2_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE12__find_equalIS7_EERPNS_16__tree_node_baseIPvEERPNS_15__tree_end_nodeISO_EERKT_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE25__emplace_unique_key_argsIS7_JRKNS_21piecewise_construct_tENS_5tupleIJRKS7_EEENSO_IJEEEEEENS_4pairINS_15__tree_iteratorISD_PNS_11__tree_nodeISD_PvEEiEEbEERKT_DpOT0_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE7destroyEPNS_11__tree_nodeISD_PvEE;
_ZNSt3__16vectorIaNS_9allocatorIaEEE6insertIPKaEENS_9enable_ifIXaasr21__is_forward_iteratorIT_EE5valuesr16is_constructibleIaNS_15iterator_traitsIS8_E9referenceEEE5valueENS_11__wrap_iterIPaEEE4typeENSC_IS6_EES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb0ELj0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb1ELj0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
@@ -1289,12 +1276,6 @@
_ZTCN7android2os17BpServiceCallbackE0_NS_10IInterfaceE;
_ZTCN7android2os17BpServiceCallbackE0_NS_11BpInterfaceINS0_16IServiceCallbackEEE;
_ZTCN7android2os17BpServiceCallbackE4_NS_9BpRefBaseE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_10IInterfaceE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_11BnInterfaceINS_2os15IClientCallbackEEE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os15IClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os16BnClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE4_NS_7BBinderE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE4_NS_7IBinderE;
_ZTCN7android7BBinderE0_NS_7IBinderE;
_ZTCN7android7content2pm21IPackageManagerNativeE0_NS_10IInterfaceE;
_ZTCN7android7content2pm22BnPackageManagerNativeE0_NS_10IInterfaceE;
@@ -1379,7 +1360,6 @@
_ZTTN7android2os16IServiceCallbackE;
_ZTTN7android2os17BnServiceCallbackE;
_ZTTN7android2os17BpServiceCallbackE;
- _ZTTN7android6binder8internal25ClientCounterCallbackImplE;
_ZTTN7android7BBinderE;
_ZTTN7android7content2pm21IPackageManagerNativeE;
_ZTTN7android7content2pm22BnPackageManagerNativeE;
@@ -1506,7 +1486,6 @@
_ZTVN7android2os17BpServiceCallbackE;
_ZTVN7android2os17PersistableBundleE;
_ZTVN7android2os20ParcelFileDescriptorE;
- _ZTVN7android6binder8internal25ClientCounterCallbackImplE;
_ZTVN7android6VectorIiEE;
_ZTVN7android6VectorINS_12ProcessState12handle_entryEEE;
_ZTVN7android6VectorINS_2spINS_18BufferedTextOutput11BufferStateEEEEE;
diff --git a/libs/binder/libbinder.arm64.map b/libs/binder/libbinder.arm64.map
index dc34de8..538fc1f 100644
--- a/libs/binder/libbinder.arm64.map
+++ b/libs/binder/libbinder.arm64.map
@@ -390,15 +390,6 @@
_ZN7android6binder8internal21ClientCounterCallback25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
_ZN7android6binder8internal21ClientCounterCallbackC1Ev;
_ZN7android6binder8internal21ClientCounterCallbackC2Ev;
- _ZN7android6binder8internal25ClientCounterCallbackImpl10reRegisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl11tryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl12forcePersistEb;
- _ZN7android6binder8internal25ClientCounterCallbackImpl13tryUnregisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl15registerServiceERKNS_2spINS_7IBinderEEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEbi;
- _ZN7android6binder8internal25ClientCounterCallbackImpl16maybeTryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl23assertRegisteredServiceERKNS_2spINS_7IBinderEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl9onClientsERKNS_2spINS_7IBinderEEEb;
_ZN7android6Parcel10appendFromEPKS0_mm;
_ZN7android6Parcel10markForRpcERKNS_2spINS_10RpcSessionEEE;
_ZN7android6Parcel10writeFloatEf;
@@ -1213,9 +1204,6 @@
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ES3_EENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE5eraseENS_21__tree_const_iteratorIS4_PNS_11__tree_nodeIS4_PvEElEE;
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ES3_EENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
_ZNSt3__16__treeINS_12__value_typeINS_11__thread_idENS_6threadEEENS_19__map_value_compareIS2_S4_NS_4lessIS2_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE12__find_equalIS7_EERPNS_16__tree_node_baseIPvEERPNS_15__tree_end_nodeISO_EERKT_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE25__emplace_unique_key_argsIS7_JRKNS_21piecewise_construct_tENS_5tupleIJRKS7_EEENSO_IJEEEEEENS_4pairINS_15__tree_iteratorISD_PNS_11__tree_nodeISD_PvEElEEbEERKT_DpOT0_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE7destroyEPNS_11__tree_nodeISD_PvEE;
_ZNSt3__16vectorIaNS_9allocatorIaEEE6insertIPKaEENS_9enable_ifIXaasr21__is_forward_iteratorIT_EE5valuesr16is_constructibleIaNS_15iterator_traitsIS8_E9referenceEEE5valueENS_11__wrap_iterIPaEEE4typeENSC_IS6_EES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb0ELm0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb1ELm0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
@@ -1339,12 +1327,6 @@
_ZTCN7android2os17BpServiceCallbackE0_NS_10IInterfaceE;
_ZTCN7android2os17BpServiceCallbackE0_NS_11BpInterfaceINS0_16IServiceCallbackEEE;
_ZTCN7android2os17BpServiceCallbackE8_NS_9BpRefBaseE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_10IInterfaceE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_11BnInterfaceINS_2os15IClientCallbackEEE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os15IClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os16BnClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE8_NS_7BBinderE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE8_NS_7IBinderE;
_ZTCN7android7BBinderE0_NS_7IBinderE;
_ZTCN7android7content2pm21IPackageManagerNativeE0_NS_10IInterfaceE;
_ZTCN7android7content2pm22BnPackageManagerNativeE0_NS_10IInterfaceE;
@@ -1433,7 +1415,6 @@
_ZTTN7android2os16IServiceCallbackE;
_ZTTN7android2os17BnServiceCallbackE;
_ZTTN7android2os17BpServiceCallbackE;
- _ZTTN7android6binder8internal25ClientCounterCallbackImplE;
_ZTTN7android7BBinderE;
_ZTTN7android7content2pm21IPackageManagerNativeE;
_ZTTN7android7content2pm22BnPackageManagerNativeE;
@@ -1565,7 +1546,6 @@
_ZTVN7android2os17BpServiceCallbackE;
_ZTVN7android2os17PersistableBundleE;
_ZTVN7android2os20ParcelFileDescriptorE;
- _ZTVN7android6binder8internal25ClientCounterCallbackImplE;
_ZTVN7android6VectorIiEE;
_ZTVN7android6VectorINS_12ProcessState12handle_entryEEE;
_ZTVN7android6VectorINS_2spINS_18BufferedTextOutput11BufferStateEEEEE;
diff --git a/libs/binder/libbinder.arm64.vendor.map b/libs/binder/libbinder.arm64.vendor.map
index 971ba92..044cc82 100644
--- a/libs/binder/libbinder.arm64.vendor.map
+++ b/libs/binder/libbinder.arm64.vendor.map
@@ -359,15 +359,6 @@
_ZN7android6binder8internal21ClientCounterCallback25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
_ZN7android6binder8internal21ClientCounterCallbackC1Ev;
_ZN7android6binder8internal21ClientCounterCallbackC2Ev;
- _ZN7android6binder8internal25ClientCounterCallbackImpl10reRegisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl11tryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl12forcePersistEb;
- _ZN7android6binder8internal25ClientCounterCallbackImpl13tryUnregisterEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl15registerServiceERKNS_2spINS_7IBinderEEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEEbi;
- _ZN7android6binder8internal25ClientCounterCallbackImpl16maybeTryShutdownEv;
- _ZN7android6binder8internal25ClientCounterCallbackImpl23assertRegisteredServiceERKNS_2spINS_7IBinderEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl25setActiveServicesCallbackERKNSt3__18functionIFbbEEE;
- _ZN7android6binder8internal25ClientCounterCallbackImpl9onClientsERKNS_2spINS_7IBinderEEEb;
_ZN7android6Parcel10appendFromEPKS0_mm;
_ZN7android6Parcel10markForRpcERKNS_2spINS_10RpcSessionEEE;
_ZN7android6Parcel10writeFloatEf;
@@ -1158,9 +1149,6 @@
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ES3_EENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE5eraseENS_21__tree_const_iteratorIS4_PNS_11__tree_nodeIS4_PvEElEE;
_ZNSt3__16__treeINS_12__value_typeIN7android8String16ES3_EENS_19__map_value_compareIS3_S4_NS_4lessIS3_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
_ZNSt3__16__treeINS_12__value_typeINS_11__thread_idENS_6threadEEENS_19__map_value_compareIS2_S4_NS_4lessIS2_EELb1EEENS_9allocatorIS4_EEE7destroyEPNS_11__tree_nodeIS4_PvEE;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE12__find_equalIS7_EERPNS_16__tree_node_baseIPvEERPNS_15__tree_end_nodeISO_EERKT_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE25__emplace_unique_key_argsIS7_JRKNS_21piecewise_construct_tENS_5tupleIJRKS7_EEENSO_IJEEEEEENS_4pairINS_15__tree_iteratorISD_PNS_11__tree_nodeISD_PvEElEEbEERKT_DpOT0_;
- _ZNSt3__16__treeINS_12__value_typeINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN7android6binder8internal25ClientCounterCallbackImpl7ServiceEEENS_19__map_value_compareIS7_SD_NS_4lessIS7_EELb1EEENS5_ISD_EEE7destroyEPNS_11__tree_nodeISD_PvEE;
_ZNSt3__16vectorIaNS_9allocatorIaEEE6insertIPKaEENS_9enable_ifIXaasr21__is_forward_iteratorIT_EE5valuesr16is_constructibleIaNS_15iterator_traitsIS8_E9referenceEEE5valueENS_11__wrap_iterIPaEEE4typeENSC_IS6_EES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb0ELm0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
_ZNSt3__16vectorIbNS_9allocatorIbEEE18__construct_at_endINS_14__bit_iteratorIS3_Lb1ELm0EEEEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeES8_S8_;
@@ -1274,12 +1262,6 @@
_ZTCN7android2os17BpServiceCallbackE0_NS_10IInterfaceE;
_ZTCN7android2os17BpServiceCallbackE0_NS_11BpInterfaceINS0_16IServiceCallbackEEE;
_ZTCN7android2os17BpServiceCallbackE8_NS_9BpRefBaseE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_10IInterfaceE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_11BnInterfaceINS_2os15IClientCallbackEEE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os15IClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE0_NS_2os16BnClientCallbackE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE8_NS_7BBinderE;
- _ZTCN7android6binder8internal25ClientCounterCallbackImplE8_NS_7IBinderE;
_ZTCN7android7BBinderE0_NS_7IBinderE;
_ZTCN7android7content2pm21IPackageManagerNativeE0_NS_10IInterfaceE;
_ZTCN7android7content2pm22BnPackageManagerNativeE0_NS_10IInterfaceE;
@@ -1364,7 +1346,6 @@
_ZTTN7android2os16IServiceCallbackE;
_ZTTN7android2os17BnServiceCallbackE;
_ZTTN7android2os17BpServiceCallbackE;
- _ZTTN7android6binder8internal25ClientCounterCallbackImplE;
_ZTTN7android7BBinderE;
_ZTTN7android7content2pm21IPackageManagerNativeE;
_ZTTN7android7content2pm22BnPackageManagerNativeE;
@@ -1489,7 +1470,6 @@
_ZTVN7android2os17BpServiceCallbackE;
_ZTVN7android2os17PersistableBundleE;
_ZTVN7android2os20ParcelFileDescriptorE;
- _ZTVN7android6binder8internal25ClientCounterCallbackImplE;
_ZTVN7android6VectorIiEE;
_ZTVN7android6VectorINS_12ProcessState12handle_entryEEE;
_ZTVN7android6VectorINS_2spINS_18BufferedTextOutput11BufferStateEEEEE;
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index e15e11c..ac8feaa 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -132,8 +132,7 @@
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
int width, int height, int32_t format)
- : mName(name),
- mSurfaceControl(surface),
+ : mSurfaceControl(surface),
mSize(width, height),
mRequestedSize(mSize),
mFormat(format),
@@ -150,6 +149,7 @@
GraphicBuffer::USAGE_HW_TEXTURE,
1, false);
static int32_t id = 0;
+ mName = name + "#" + std::to_string(id);
auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(id);
id++;
@@ -197,15 +197,18 @@
}
SurfaceComposerClient::Transaction t;
+ const bool setBackpressureFlag = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
bool applyTransaction = false;
- if (!SurfaceControl::isSameSurface(mSurfaceControl, surface)) {
- mSurfaceControl = surface;
- t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
- layer_state_t::eEnableBackpressure);
- applyTransaction = true;
- }
+ // Always update the native object even though they might have the same layer handle, so we can
+ // get the updated transform hint from WM.
+ mSurfaceControl = surface;
if (mSurfaceControl != nullptr) {
+ if (setBackpressureFlag) {
+ t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
+ layer_state_t::eEnableBackpressure);
+ applyTransaction = true;
+ }
mTransformHint = mSurfaceControl->getTransformHint();
mBufferItemConsumer->setTransformHint(mTransformHint);
}
@@ -221,7 +224,7 @@
// We only need to update the scale if we've received at least one buffer. The reason
// for this is the scale is calculated based on the requested size and buffer size.
// If there's no buffer, the scale will always be 1.
- if (mLastBufferInfo.hasBuffer) {
+ if (mSurfaceControl != nullptr && mLastBufferInfo.hasBuffer) {
t.setDestinationFrame(mSurfaceControl,
Rect(0, 0, newSize.getWidth(), newSize.getHeight()));
}
@@ -313,24 +316,24 @@
// BBQ. This is because if the BBQ is destroyed, then the buffers will be released by the client.
// So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
// Otherwise, this is a no-op.
-static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, uint64_t graphicBufferId,
+static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, const ReleaseCallbackId& id,
const sp<Fence>& releaseFence, uint32_t transformHint,
uint32_t currentMaxAcquiredBufferCount) {
sp<BLASTBufferQueue> blastBufferQueue = context.promote();
- ALOGV("releaseBufferCallbackThunk graphicBufferId=%" PRIu64 " blastBufferQueue=%s",
- graphicBufferId, blastBufferQueue ? "alive" : "dead");
if (blastBufferQueue) {
- blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint,
+ blastBufferQueue->releaseBufferCallback(id, releaseFence, transformHint,
currentMaxAcquiredBufferCount);
+ } else {
+ ALOGV("releaseBufferCallbackThunk %s blastBufferQueue is dead", id.to_string().c_str());
}
}
-void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId,
+void BLASTBufferQueue::releaseBufferCallback(const ReleaseCallbackId& id,
const sp<Fence>& releaseFence, uint32_t transformHint,
uint32_t currentMaxAcquiredBufferCount) {
ATRACE_CALL();
std::unique_lock _lock{mMutex};
- BQA_LOGV("releaseBufferCallback graphicBufferId=%" PRIu64, graphicBufferId);
+ BQA_LOGV("releaseBufferCallback %s", id.to_string().c_str());
if (mSurfaceControl != nullptr) {
mTransformHint = transformHint;
@@ -343,25 +346,26 @@
// on a lower refresh rate than the max supported. We only do that for EGL
// clients as others don't care about latency
const bool isEGL = [&] {
- const auto it = mSubmitted.find(graphicBufferId);
+ const auto it = mSubmitted.find(id);
return it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;
}();
const auto numPendingBuffersToHold =
isEGL ? std::max(0u, mMaxAcquiredBuffers - currentMaxAcquiredBufferCount) : 0;
- mPendingRelease.emplace_back(ReleasedBuffer{graphicBufferId, releaseFence});
+ mPendingRelease.emplace_back(ReleasedBuffer{id, releaseFence});
// Release all buffers that are beyond the ones that we need to hold
while (mPendingRelease.size() > numPendingBuffersToHold) {
const auto releaseBuffer = mPendingRelease.front();
mPendingRelease.pop_front();
- auto it = mSubmitted.find(releaseBuffer.bufferId);
+ auto it = mSubmitted.find(releaseBuffer.callbackId);
if (it == mSubmitted.end()) {
- BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64,
- graphicBufferId);
+ BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
+ releaseBuffer.callbackId.to_string().c_str());
return;
}
mNumAcquired--;
+ BQA_LOGV("released %s", id.to_string().c_str());
mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
mSubmitted.erase(it);
processNextBufferLocked(false /* useNextTransaction */);
@@ -428,7 +432,9 @@
}
mNumAcquired++;
- mSubmitted[buffer->getId()] = bufferItem;
+ mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
+ ReleaseCallbackId releaseCallbackId(buffer->getId(), mLastAcquiredFrameNumber);
+ mSubmitted[releaseCallbackId] = bufferItem;
bool needsDisconnect = false;
mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect);
@@ -442,7 +448,6 @@
incStrong((void*)transactionCallbackThunk);
Rect crop = computeCrop(bufferItem);
- mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
bufferItem.mScalingMode, crop);
@@ -451,7 +456,7 @@
std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4);
- t->setBuffer(mSurfaceControl, buffer, releaseBufferCallback);
+ t->setBuffer(mSurfaceControl, buffer, releaseCallbackId, releaseBufferCallback);
t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
@@ -510,11 +515,11 @@
BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
" applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d"
- " graphicBufferId=%" PRIu64,
+ " graphicBufferId=%" PRIu64 "%s",
mSize.width, mSize.height, bufferItem.mFrameNumber, toString(applyTransaction),
bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "",
- static_cast<uint32_t>(mPendingTransactions.size()),
- bufferItem.mGraphicBuffer->getId());
+ static_cast<uint32_t>(mPendingTransactions.size()), bufferItem.mGraphicBuffer->getId(),
+ bufferItem.mAutoRefresh ? " mAutoRefresh" : "");
}
Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 17499ec..98e8b54 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -125,7 +125,7 @@
for (const auto& data : jankData) {
SAFE_PARCEL(output->writeParcelable, data);
}
- SAFE_PARCEL(output->writeUint64, previousBufferId);
+ SAFE_PARCEL(output->writeParcelable, previousReleaseCallbackId);
return NO_ERROR;
}
@@ -149,7 +149,7 @@
SAFE_PARCEL(input->readParcelable, &data);
jankData.push_back(data);
}
- SAFE_PARCEL(input->readUint64, &previousBufferId);
+ SAFE_PARCEL(input->readParcelable, &previousReleaseCallbackId);
return NO_ERROR;
}
@@ -253,11 +253,11 @@
stats);
}
- void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence, uint32_t transformHint,
- uint32_t currentMaxAcquiredBufferCount) override {
+ void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
+ uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override {
callRemoteAsync<decltype(
&ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER,
- graphicBufferId, releaseFence,
+ callbackId, releaseFence,
transformHint,
currentMaxAcquiredBufferCount);
}
@@ -308,4 +308,18 @@
return NO_ERROR;
}
+status_t ReleaseCallbackId::writeToParcel(Parcel* output) const {
+ SAFE_PARCEL(output->writeUint64, bufferId);
+ SAFE_PARCEL(output->writeUint64, framenumber);
+ return NO_ERROR;
+}
+
+status_t ReleaseCallbackId::readFromParcel(const Parcel* input) {
+ SAFE_PARCEL(input->readUint64, &bufferId);
+ SAFE_PARCEL(input->readUint64, &framenumber);
+ return NO_ERROR;
+}
+
+const ReleaseCallbackId ReleaseCallbackId::INVALID_ID = ReleaseCallbackId(0, 0);
+
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index fd78309..6ea070ea 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -197,15 +197,16 @@
}
}
-void TransactionCompletedListener::setReleaseBufferCallback(uint64_t graphicBufferId,
+void TransactionCompletedListener::setReleaseBufferCallback(const ReleaseCallbackId& callbackId,
ReleaseBufferCallback listener) {
std::scoped_lock<std::mutex> lock(mMutex);
- mReleaseBufferCallbacks[graphicBufferId] = listener;
+ mReleaseBufferCallbacks[callbackId] = listener;
}
-void TransactionCompletedListener::removeReleaseBufferCallback(uint64_t graphicBufferId) {
+void TransactionCompletedListener::removeReleaseBufferCallback(
+ const ReleaseCallbackId& callbackId) {
std::scoped_lock<std::mutex> lock(mMutex);
- mReleaseBufferCallbacks.erase(graphicBufferId);
+ mReleaseBufferCallbacks.erase(callbackId);
}
void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie,
@@ -319,14 +320,15 @@
// and call them. This is a performance optimization when we have a transaction
// callback and a release buffer callback happening at the same time to avoid an
// additional ipc call from the server.
- if (surfaceStats.previousBufferId) {
+ if (surfaceStats.previousReleaseCallbackId != ReleaseCallbackId::INVALID_ID) {
ReleaseBufferCallback callback;
{
std::scoped_lock<std::mutex> lock(mMutex);
- callback = popReleaseBufferCallbackLocked(surfaceStats.previousBufferId);
+ callback = popReleaseBufferCallbackLocked(
+ surfaceStats.previousReleaseCallbackId);
}
if (callback) {
- callback(surfaceStats.previousBufferId,
+ callback(surfaceStats.previousReleaseCallbackId,
surfaceStats.previousReleaseFence
? surfaceStats.previousReleaseFence
: Fence::NO_FENCE,
@@ -362,25 +364,26 @@
}
}
-void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence,
- uint32_t transformHint,
+void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
+ sp<Fence> releaseFence, uint32_t transformHint,
uint32_t currentMaxAcquiredBufferCount) {
ReleaseBufferCallback callback;
{
std::scoped_lock<std::mutex> lock(mMutex);
- callback = popReleaseBufferCallbackLocked(graphicBufferId);
+ callback = popReleaseBufferCallbackLocked(callbackId);
}
if (!callback) {
- ALOGE("Could not call release buffer callback, buffer not found %" PRIu64, graphicBufferId);
+ ALOGE("Could not call release buffer callback, buffer not found %s",
+ callbackId.to_string().c_str());
return;
}
- callback(graphicBufferId, releaseFence, transformHint, currentMaxAcquiredBufferCount);
+ callback(callbackId, releaseFence, transformHint, currentMaxAcquiredBufferCount);
}
ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked(
- uint64_t graphicBufferId) {
+ const ReleaseCallbackId& callbackId) {
ReleaseBufferCallback callback;
- auto itr = mReleaseBufferCallbacks.find(graphicBufferId);
+ auto itr = mReleaseBufferCallbacks.find(callbackId);
if (itr == mReleaseBufferCallbacks.end()) {
return nullptr;
}
@@ -1258,7 +1261,7 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
- const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
+ const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const ReleaseCallbackId& id,
ReleaseBufferCallback callback) {
layer_state_t* s = getLayerState(sc);
if (!s) {
@@ -1271,7 +1274,7 @@
if (mIsAutoTimestamp) {
mDesiredPresentTime = systemTime();
}
- setReleaseBufferCallback(s, callback);
+ setReleaseBufferCallback(s, id, callback);
registerSurfaceControlForCallback(sc);
@@ -1286,10 +1289,13 @@
s->what &= ~static_cast<uint64_t>(layer_state_t::eReleaseBufferListenerChanged);
s->releaseBufferListener = nullptr;
- TransactionCompletedListener::getInstance()->removeReleaseBufferCallback(s->buffer->getId());
+ auto listener = TransactionCompletedListener::getInstance();
+ listener->removeReleaseBufferCallback(s->releaseCallbackId);
+ s->releaseCallbackId = ReleaseCallbackId::INVALID_ID;
}
void SurfaceComposerClient::Transaction::setReleaseBufferCallback(layer_state_t* s,
+ const ReleaseCallbackId& id,
ReleaseBufferCallback callback) {
if (!callback) {
return;
@@ -1303,8 +1309,9 @@
s->what |= layer_state_t::eReleaseBufferListenerChanged;
s->releaseBufferListener = TransactionCompletedListener::getIInstance();
+ s->releaseCallbackId = id;
auto listener = TransactionCompletedListener::getInstance();
- listener->setReleaseBufferCallback(s->buffer->getId(), callback);
+ listener->setReleaseBufferCallback(id, callback);
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence(
diff --git a/libs/gui/bufferqueue/1.0/Conversion.cpp b/libs/gui/bufferqueue/1.0/Conversion.cpp
index 3e20a37..55462c3 100644
--- a/libs/gui/bufferqueue/1.0/Conversion.cpp
+++ b/libs/gui/bufferqueue/1.0/Conversion.cpp
@@ -1187,14 +1187,15 @@
*/
constexpr size_t minFlattenedSize(
HGraphicBufferProducer::QueueBufferInput const& /* t */) {
- return sizeof(int64_t) + // timestamp
- sizeof(int) + // isAutoTimestamp
+ return sizeof(int64_t) + // timestamp
+ sizeof(int) + // isAutoTimestamp
sizeof(android_dataspace) + // dataSpace
- sizeof(::android::Rect) + // crop
- sizeof(int) + // scalingMode
- sizeof(uint32_t) + // transform
- sizeof(uint32_t) + // stickyTransform
- sizeof(bool); // getFrameTimestamps
+ sizeof(::android::Rect) + // crop
+ sizeof(int) + // scalingMode
+ sizeof(uint32_t) + // transform
+ sizeof(uint32_t) + // stickyTransform
+ sizeof(bool) + // getFrameTimestamps
+ sizeof(int); // slot
}
/**
@@ -1267,6 +1268,7 @@
return status;
}
FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
+ FlattenableUtils::write(buffer, size, -1 /*slot*/);
return NO_ERROR;
}
@@ -1319,7 +1321,7 @@
if (status != NO_ERROR) {
return status;
}
- // HdrMetadata ignored
+ // HdrMetadata and slot ignored
return unflatten(&(t->surfaceDamage), buffer, size);
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 26c7285..0d6a673 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -89,7 +89,7 @@
void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
const std::vector<SurfaceControlStats>& stats);
- void releaseBufferCallback(uint64_t graphicBufferId, const sp<Fence>& releaseFence,
+ void releaseBufferCallback(const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount);
void setNextTransaction(SurfaceComposerClient::Transaction *t);
void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber);
@@ -144,13 +144,14 @@
// Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
// buffer or the buffer has been presented and a new buffer is ready to be presented.
- std::unordered_map<uint64_t /* bufferId */, BufferItem> mSubmitted GUARDED_BY(mMutex);
+ std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
+ GUARDED_BY(mMutex);
// Keep a queue of the released buffers instead of immediately releasing
// the buffers back to the buffer queue. This would be controlled by SF
// setting the max acquired buffer count.
struct ReleasedBuffer {
- uint64_t bufferId;
+ ReleaseCallbackId callbackId;
sp<Fence> releaseFence;
};
std::deque<ReleasedBuffer> mPendingRelease GUARDED_BY(mMutex);
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index d286c34..937095c 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -53,6 +53,36 @@
std::size_t operator()(const CallbackId& key) const { return std::hash<int64_t>()(key.id); }
};
+class ReleaseCallbackId : public Parcelable {
+public:
+ static const ReleaseCallbackId INVALID_ID;
+
+ uint64_t bufferId;
+ uint64_t framenumber;
+ ReleaseCallbackId() {}
+ ReleaseCallbackId(uint64_t bufferId, uint64_t framenumber)
+ : bufferId(bufferId), framenumber(framenumber) {}
+ status_t writeToParcel(Parcel* output) const override;
+ status_t readFromParcel(const Parcel* input) override;
+
+ bool operator==(const ReleaseCallbackId& rhs) const {
+ return bufferId == rhs.bufferId && framenumber == rhs.framenumber;
+ }
+ bool operator!=(const ReleaseCallbackId& rhs) const { return !operator==(rhs); }
+ std::string to_string() const {
+ if (*this == INVALID_ID) return "INVALID_ID";
+
+ return "bufferId:" + std::to_string(bufferId) +
+ " framenumber:" + std::to_string(framenumber);
+ }
+};
+
+struct ReleaseBufferCallbackIdHash {
+ std::size_t operator()(const ReleaseCallbackId& key) const {
+ return std::hash<uint64_t>()(key.bufferId);
+ }
+};
+
class FrameEventHistoryStats : public Parcelable {
public:
status_t writeToParcel(Parcel* output) const override;
@@ -103,7 +133,7 @@
SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence,
uint32_t hint, uint32_t currentMaxAcquiredBuffersCount,
FrameEventHistoryStats frameEventStats, std::vector<JankData> jankData,
- uint64_t previousBufferId)
+ ReleaseCallbackId previousReleaseCallbackId)
: surfaceControl(sc),
acquireTime(time),
previousReleaseFence(prevReleaseFence),
@@ -111,7 +141,7 @@
currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount),
eventStats(frameEventStats),
jankData(std::move(jankData)),
- previousBufferId(previousBufferId) {}
+ previousReleaseCallbackId(previousReleaseCallbackId) {}
sp<IBinder> surfaceControl;
nsecs_t acquireTime = -1;
@@ -120,7 +150,7 @@
uint32_t currentMaxAcquiredBufferCount = 0;
FrameEventHistoryStats eventStats;
std::vector<JankData> jankData;
- uint64_t previousBufferId;
+ ReleaseCallbackId previousReleaseCallbackId;
};
class TransactionStats : public Parcelable {
@@ -161,7 +191,7 @@
virtual void onTransactionCompleted(ListenerStats stats) = 0;
- virtual void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence,
+ virtual void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
uint32_t transformHint,
uint32_t currentMaxAcquiredBufferCount) = 0;
};
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 16430b3..8ac1e5d 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -234,6 +234,12 @@
// layers only. The callback includes a release fence as well as the graphic
// buffer id to identify the buffer.
sp<ITransactionCompletedListener> releaseBufferListener;
+
+ // Keeps track of the release callback id associated with the listener. This
+ // is not sent to the server since the id can be reconstructed there. This
+ // is used to remove the old callback from the client process map if it is
+ // overwritten by another setBuffer call.
+ ReleaseCallbackId releaseCallbackId;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 13994fd..c2963b5 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -82,7 +82,7 @@
std::function<void(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
const std::vector<SurfaceControlStats>& /*stats*/)>;
using ReleaseBufferCallback =
- std::function<void(uint64_t /* graphicsBufferId */, const sp<Fence>& /*releaseFence*/,
+ std::function<void(const ReleaseCallbackId&, const sp<Fence>& /*releaseFence*/,
uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount)>;
using SurfaceStatsCallback =
@@ -397,8 +397,9 @@
void cacheBuffers();
void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc);
- void setReleaseBufferCallback(layer_state_t* state, ReleaseBufferCallback callback);
- void removeReleaseBufferCallback(layer_state_t* state);
+ void setReleaseBufferCallback(layer_state_t*, const ReleaseCallbackId&,
+ ReleaseBufferCallback);
+ void removeReleaseBufferCallback(layer_state_t*);
public:
Transaction();
@@ -470,6 +471,7 @@
Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc,
bool transformToDisplayInverse);
Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
+ const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID,
ReleaseBufferCallback callback = nullptr);
Transaction& setCachedBuffer(const sp<SurfaceControl>& sc, int32_t bufferId);
Transaction& setAcquireFence(const sp<SurfaceControl>& sc, const sp<Fence>& fence);
@@ -678,7 +680,7 @@
std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> mCallbacks
GUARDED_BY(mMutex);
std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex);
- std::unordered_map<uint64_t /* graphicsBufferId */, ReleaseBufferCallback>
+ std::unordered_map<ReleaseCallbackId, ReleaseBufferCallback, ReleaseBufferCallbackIdHash>
mReleaseBufferCallbacks GUARDED_BY(mMutex);
// This is protected by mSurfaceStatsListenerMutex, but GUARDED_BY isn't supported for
@@ -717,16 +719,16 @@
SurfaceStatsCallback listener);
void removeSurfaceStatsListener(void* context, void* cookie);
- void setReleaseBufferCallback(uint64_t /* graphicsBufferId */, ReleaseBufferCallback);
- void removeReleaseBufferCallback(uint64_t /* graphicsBufferId */);
+ void setReleaseBufferCallback(const ReleaseCallbackId&, ReleaseBufferCallback);
+ void removeReleaseBufferCallback(const ReleaseCallbackId&);
// BnTransactionCompletedListener overrides
void onTransactionCompleted(ListenerStats stats) override;
- void onReleaseBuffer(uint64_t /* graphicsBufferId */, sp<Fence> releaseFence,
- uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override;
+ void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence, uint32_t transformHint,
+ uint32_t currentMaxAcquiredBufferCount) override;
private:
- ReleaseBufferCallback popReleaseBufferCallbackLocked(uint64_t /* graphicsBufferId */);
+ ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&);
};
} // namespace android
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index 3038d9d..474a1e4 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -42,16 +42,15 @@
const int INVALID_INPUT_EVENT_ID = 0;
/**
- * The injected event was originally sent from InputDispatcher. Most likely, the journey of the
- * event looked as follows:
- * InputDispatcherPolicyInterface::filterInputEvent -> InputFilter.java::onInputEvent ->
- * InputFilter.java::sendInputEvent -> InputDispatcher::injectInputEvent, without being modified
- * along the way.
- */
- const int POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000;
-
- /**
- * The input event was injected from accessibility
+ * The input event was injected from accessibility. Used in policyFlags for input event
+ * injection.
*/
const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000;
+
+ /**
+ * The input event was generated or modified by accessibility service.
+ * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either
+ * set of flags, including in input/Input.h and in android/input.h.
+ */
+ const int INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
}
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index b5dd8ac..467f848 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -1028,20 +1028,17 @@
return mProtectedEGLContext != EGL_NO_CONTEXT;
}
-bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
- if (useProtectedContext == mInProtectedContext) {
- return true;
+void GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
+ if (useProtectedContext == mInProtectedContext ||
+ (useProtectedContext && !supportsProtectedContent())) {
+ return;
}
- if (useProtectedContext && mProtectedEGLContext == EGL_NO_CONTEXT) {
- return false;
- }
+
const EGLSurface surface = useProtectedContext ? mProtectedStubSurface : mStubSurface;
const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
- const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
- if (success) {
+ if (eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE) {
mInProtectedContext = useProtectedContext;
}
- return success;
}
EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
bool isProtected,
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 915dba3..4cb1b42 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -62,7 +62,7 @@
void deleteTextures(size_t count, uint32_t const* names) override;
bool isProtected() const override { return mInProtectedContext; }
bool supportsProtectedContent() const override;
- bool useProtectedContext(bool useProtectedContext) override;
+ void useProtectedContext(bool useProtectedContext) override;
status_t drawLayers(const DisplaySettings& display,
const std::vector<const LayerSettings*>& layers,
const std::shared_ptr<ExternalTexture>& buffer,
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index ac0affb..5964bc3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -127,7 +127,7 @@
virtual bool supportsProtectedContent() const = 0;
// Attempt to switch RenderEngine into and out of protectedContext mode
- virtual bool useProtectedContext(bool useProtectedContext) = 0;
+ virtual void useProtectedContext(bool useProtectedContext) = 0;
// Notify RenderEngine of changes to the dimensions of the primary display
// so that it can configure its internal caches accordingly.
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 0175af3..a4aa9ea 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -44,7 +44,7 @@
MOCK_CONST_METHOD0(getMaxViewportDims, size_t());
MOCK_CONST_METHOD0(isProtected, bool());
MOCK_CONST_METHOD0(supportsProtectedContent, bool());
- MOCK_METHOD1(useProtectedContext, bool(bool));
+ MOCK_METHOD1(useProtectedContext, void(bool));
MOCK_METHOD0(cleanupPostRender, void());
MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool());
MOCK_METHOD6(drawLayers,
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 725f57b..081de2e 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -41,6 +41,10 @@
0.f, 1.1f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f);
+const auto kFlip = mat4(1.1f, -0.1f, 0.f, 0.f,
+ 0.1f, 1.1f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 2.f, 2.f, 0.f, 1.f);
// clang-format on
// When setting layer.sourceDataspace, whether it matches the destination or not determines whether
// a color correction effect is added to the shader.
@@ -99,6 +103,9 @@
LayerSettings layer{
.geometry =
Geometry{
+ // The position transform doesn't matter when the reduced shader mode
+ // in in effect. A matrix transform stage is always included.
+ .positionTransform = mat4(),
.boundaries = rect,
.roundedCornersCrop = rect,
},
@@ -109,29 +116,20 @@
}},
};
- auto threeCornerRadii = {0.0f, 0.05f, 50.f};
- auto oneCornerRadius = {50.f};
-
- // Test both drawRect and drawRRect
auto layers = std::vector<const LayerSettings*>{&layer};
for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
layer.sourceDataspace = dataspace;
- for (bool identity : {true, false}) {
- layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
- // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
- // due to animating corner radius.
- // For the non-idenity matrix, only the large corner radius will create a new shader.
- for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
- // roundedCornersCrop is always set, but it is this radius that triggers the
- // behavior
- layer.geometry.roundedCornersRadius = roundedCornersRadius;
- for (bool isOpaque : {true, false}) {
- layer.source.buffer.isOpaque = isOpaque;
- for (auto alpha : {half(.23999f), half(1.0f)}) {
- layer.alpha = alpha;
- renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
- base::unique_fd(), nullptr);
- }
+ // Cache shaders for both rects and round rects.
+ // In reduced shader mode, all non-zero round rect radii get the same code path.
+ for (float roundedCornersRadius : {0.0f, 50.0f}) {
+ // roundedCornersCrop is always set, but the radius triggers the behavior
+ layer.geometry.roundedCornersRadius = roundedCornersRadius;
+ for (bool isOpaque : {true, false}) {
+ layer.source.buffer.isOpaque = isOpaque;
+ for (auto alpha : {half(.2f), half(1.0f)}) {
+ layer.alpha = alpha;
+ renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
}
}
}
@@ -157,7 +155,7 @@
auto layers = std::vector<const LayerSettings*>{&layer};
for (auto transform : {mat4(), kScaleAndTranslate}) {
layer.geometry.positionTransform = transform;
- for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
+ for (float roundedCornersRadius : {0.0f, 50.f}) {
layer.geometry.roundedCornersRadius = roundedCornersRadius;
renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
base::unique_fd(), nullptr);
@@ -225,11 +223,9 @@
layer.source = pixelSource;
for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
layer.sourceDataspace = dataspace;
- // Produce a CircularRRect clip and an EllipticalRRect clip
+ // Produce a CircularRRect clip and an EllipticalRRect clip.
for (auto transform : {kScaleAndTranslate, kScaleAsymmetric}) {
layer.geometry.positionTransform = transform;
- // In real use, I saw alpha of 1.0 and 0.999, probably a mistake, but cache both
- // shaders.
for (float alpha : {0.5f, 1.f}) {
layer.alpha = alpha,
renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
@@ -240,6 +236,69 @@
}
}
+static void drawPIPImageLayer(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ // Note that this flip matrix only makes a difference when clipping,
+ // which happens in this layer because the roundrect crop is just a bit
+ // larger than the layer bounds.
+ .positionTransform = kFlip,
+ .boundaries = rect,
+ .roundedCornersRadius = 94.2551,
+ .roundedCornersCrop = FloatRect(
+ -93.75, 0, displayRect.width() + 93.75, displayRect.height()),
+ },
+ .source = PixelSource{.buffer =
+ Buffer{
+ .buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .isOpaque = 0,
+ .usePremultipliedAlpha = 1,
+ }},
+ .sourceDataspace = kOtherDataSpace,
+ .alpha = 1,
+
+ };
+
+ auto layers = std::vector<const LayerSettings*>{&layer};
+ renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
+}
+
+static void drawHolePunchLayer(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ FloatRect small(0, 0, displayRect.width()-20, displayRect.height()+20);
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .positionTransform = kScaleAndTranslate,
+ // the boundaries have to be smaller than the rounded crop so that
+ // clipRRect is used instead of drawRRect
+ .boundaries = small,
+ .roundedCornersRadius = 50.f,
+ .roundedCornersCrop = rect,
+ },
+ .source = PixelSource{
+ .solidColor = half3(0.f, 0.f, 0.f),
+ },
+ .sourceDataspace = kDestDataSpace,
+ .alpha = 0,
+ .disableBlending = true,
+
+ };
+
+ auto layers = std::vector<const LayerSettings*>{&layer};
+ renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
+}
+
//
// The collection of shaders cached here were found by using perfetto to record shader compiles
// during actions that involve RenderEngine, logging the layer settings, and the shader code
@@ -251,8 +310,6 @@
// kFlushAfterEveryLayer = true
// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
// gPrintSKSL = true
-//
-// TODO(b/184631553) cache the shader involved in youtube pip return.
void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
const int previousCount = renderengine->reportShadersCompiled();
if (previousCount) {
@@ -294,35 +351,46 @@
std::make_shared<ExternalTexture>(srcBuffer, *renderengine,
ExternalTexture::Usage::READABLE |
ExternalTexture::Usage::WRITEABLE);
-
- // 6 shaders
+ drawHolePunchLayer(renderengine, display, dstTexture);
drawSolidLayers(renderengine, display, dstTexture);
- // 8 shaders
drawShadowLayers(renderengine, display, srcTexture);
if (renderengine->supportsBackgroundBlur()) {
- // 2 shaders
drawBlurLayers(renderengine, display, dstTexture);
}
- // The majority of shaders are related to sampling images.
- drawImageLayers(renderengine, display, dstTexture, srcTexture);
-
// should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
-
sp<GraphicBuffer> externalBuffer =
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
1, usageExternal, "primeShaderCache_external");
const auto externalTexture =
std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
ExternalTexture::Usage::READABLE);
- // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
- // between 6 and 8 will occur in real uses.
- drawImageLayers(renderengine, display, dstTexture, externalTexture);
- // Draw layers for b/185569240.
- drawClippedLayers(renderengine, display, dstTexture, externalTexture);
+ // Another external texture with a different pixel format triggers useIsOpaqueWorkaround
+ sp<GraphicBuffer> f16ExternalBuffer =
+ new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_FP16,
+ 1, usageExternal, "primeShaderCache_external_f16");
+ const auto f16ExternalTexture =
+ std::make_shared<ExternalTexture>(f16ExternalBuffer, *renderengine,
+ ExternalTexture::Usage::READABLE);
+
+ // The majority of shaders are related to sampling images.
+ // These need to be generated with various source textures
+ // The F16 texture may not be usable on all devices, so check first that it was created with
+ // the requested usage bit.
+ auto textures = {srcTexture, externalTexture};
+ auto texturesWithF16 = {srcTexture, externalTexture, f16ExternalTexture};
+ bool canUsef16 = f16ExternalBuffer->getUsage() & GRALLOC_USAGE_HW_TEXTURE;
+
+ for (auto texture : canUsef16 ? texturesWithF16 : textures) {
+ drawImageLayers(renderengine, display, dstTexture, texture);
+ // Draw layers for b/185569240.
+ drawClippedLayers(renderengine, display, dstTexture, texture);
+ }
+
+ drawPIPImageLayer(renderengine, display, dstTexture, externalTexture);
const nsecs_t timeAfter = systemTime();
const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index cb80ef4..3c59f11 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -320,7 +320,8 @@
options.fReducedShaderVariations = true;
options.fPersistentCache = &mSkSLCacheMonitor;
mGrContext = GrDirectContext::MakeGL(glInterface, options);
- if (useProtectedContext(true)) {
+ if (supportsProtectedContent()) {
+ useProtectedContext(true);
mProtectedGrContext = GrDirectContext::MakeGL(glInterface, options);
useProtectedContext(false);
}
@@ -373,12 +374,10 @@
return mInProtectedContext ? mProtectedGrContext.get() : mGrContext.get();
}
-bool SkiaGLRenderEngine::useProtectedContext(bool useProtectedContext) {
- if (useProtectedContext == mInProtectedContext) {
- return true;
- }
- if (useProtectedContext && !supportsProtectedContent()) {
- return false;
+void SkiaGLRenderEngine::useProtectedContext(bool useProtectedContext) {
+ if (useProtectedContext == mInProtectedContext ||
+ (useProtectedContext && !supportsProtectedContent())) {
+ return;
}
// release any scratch resources before switching into a new mode
@@ -389,9 +388,8 @@
const EGLSurface surface =
useProtectedContext ? mProtectedPlaceholderSurface : mPlaceholderSurface;
const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
- const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
- if (success) {
+ if (eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE) {
mInProtectedContext = useProtectedContext;
// given that we are sharing the same thread between two GrContexts we need to
// make sure that the thread state is reset when switching between the two.
@@ -399,7 +397,6 @@
getActiveGrContext()->resetContext();
}
}
- return success;
}
base::unique_fd SkiaGLRenderEngine::flush() {
@@ -618,9 +615,9 @@
if (requiresLinearEffect) {
const ui::Dataspace inputDataspace =
- mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::UNKNOWN;
+ mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR;
const ui::Dataspace outputDataspace =
- mUseColorManagement ? display.outputDataspace : ui::Dataspace::UNKNOWN;
+ mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
LinearEffect effect = LinearEffect{.inputDataspace = inputDataspace,
.outputDataspace = outputDataspace,
@@ -762,7 +759,7 @@
}
const ui::Dataspace dstDataspace =
- mUseColorManagement ? display.outputDataspace : ui::Dataspace::UNKNOWN;
+ mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR;
sk_sp<SkSurface> dstSurface = surfaceTextureRef->getOrCreateSurface(dstDataspace, grContext);
SkCanvas* dstCanvas = mCapture->tryCapture(dstSurface.get());
@@ -1413,10 +1410,12 @@
getActiveGrContext()->setResourceCacheLimit(maxResourceBytes);
// if it is possible to switch contexts then we will resize the other context
- if (useProtectedContext(!mInProtectedContext)) {
+ const bool originalProtectedState = mInProtectedContext;
+ useProtectedContext(!mInProtectedContext);
+ if (mInProtectedContext != originalProtectedState) {
getActiveGrContext()->setResourceCacheLimit(maxResourceBytes);
// reset back to the initial context that was active when this method was called
- useProtectedContext(!mInProtectedContext);
+ useProtectedContext(originalProtectedState);
}
}
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index b30355b..a852bbc 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -64,7 +64,7 @@
int getContextPriority() override;
bool isProtected() const override { return mInProtectedContext; }
bool supportsProtectedContent() const override;
- bool useProtectedContext(bool useProtectedContext) override;
+ void useProtectedContext(bool useProtectedContext) override;
bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
void assertShadersCompiled(int numShaders) override;
void onPrimaryDisplaySizeChanged(ui::Size size) override;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 31ad63e..7cd9eca 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -44,7 +44,6 @@
virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{};
virtual bool isProtected() const override { return false; } // mInProtectedContext; }
virtual bool supportsProtectedContent() const override { return false; };
- virtual bool useProtectedContext(bool /*useProtectedContext*/) override { return false; };
virtual status_t drawLayers(const DisplaySettings& /*display*/,
const std::vector<const LayerSettings*>& /*layers*/,
const std::shared_ptr<ExternalTexture>& /*buffer*/,
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 9b044e1..fc45af9 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -167,13 +167,12 @@
float nits = xyz.y;
- // clamp to max input luminance
- nits = clamp(nits, 0.0, maxInLumi);
-
- // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
+ // if the max input luminance is less than what we can output then
+ // no tone mapping is needed as all color values will be in range.
if (maxInLumi <= maxOutLumi) {
- return xyz * (maxOutLumi / maxInLumi);
+ return xyz;
} else {
+
// three control points
const float x0 = 10.0;
const float y0 = 17.0;
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index e258741..33e3773 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -81,6 +81,7 @@
.setSupportsBackgroundBlur(true)
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
.setRenderEngineType(type())
+ .setUseColorManagerment(useColorManagement())
.build();
return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
}
@@ -110,7 +111,7 @@
.setSupportsBackgroundBlur(true)
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
.setRenderEngineType(type())
- .setUseColorManagerment(true)
+ .setUseColorManagerment(useColorManagement())
.build();
return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
}
@@ -136,16 +137,12 @@
.setSupportsBackgroundBlur(true)
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
.setRenderEngineType(type())
- // FIXME (b/189935602): This version is currently color managed.
- // We should change it and fix the tests that fail.
- //.setUseColorManagerment(false)
+ .setUseColorManagerment(useColorManagement())
.build();
return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
}
- // FIXME (b/189935602): This version is currently color managed.
- // We should change it and fix the tests that fail.
- bool useColorManagement() const override { return true; }
+ bool useColorManagement() const override { return false; }
};
class SkiaGLESCMRenderEngineFactory : public RenderEngineFactory {
@@ -166,7 +163,7 @@
.setSupportsBackgroundBlur(true)
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
.setRenderEngineType(type())
- .setUseColorManagerment(true)
+ .setUseColorManagerment(useColorManagement())
.build();
return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
}
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index c65e731..830f463 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -118,16 +118,26 @@
ASSERT_EQ(true, result);
}
-TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsFalse) {
- EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(false));
- status_t result = mThreadedRE->useProtectedContext(false);
- ASSERT_EQ(false, result);
+TEST_F(RenderEngineThreadedTest, useProtectedContext) {
+ EXPECT_CALL(*mRenderEngine, useProtectedContext(true));
+ auto& ipExpect = EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(false));
+ EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(true));
+ EXPECT_CALL(*mRenderEngine, isProtected()).After(ipExpect).WillOnce(Return(true));
+
+ mThreadedRE->useProtectedContext(true);
+ ASSERT_EQ(true, mThreadedRE->isProtected());
+
+ // call ANY synchronous function to ensure that useProtectedContext has completed.
+ mThreadedRE->getContextPriority();
+ ASSERT_EQ(true, mThreadedRE->isProtected());
}
-TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsTrue) {
- EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(true));
- status_t result = mThreadedRE->useProtectedContext(false);
- ASSERT_EQ(true, result);
+TEST_F(RenderEngineThreadedTest, useProtectedContext_quickReject) {
+ EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).Times(0);
+ EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(false));
+ mThreadedRE->useProtectedContext(false);
+ // call ANY synchronous function to ensure that useProtectedContext has completed.
+ mThreadedRE->getContextPriority();
}
TEST_F(RenderEngineThreadedTest, PostRenderCleanup_skipped) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index ea3871f..b9dabc1 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -90,6 +90,7 @@
}
mRenderEngine = factory();
+ mIsProtected = mRenderEngine->isProtected();
pthread_setname_np(pthread_self(), mThreadName);
@@ -248,10 +249,8 @@
bool RenderEngineThreaded::isProtected() const {
waitUntilInitialized();
- // ensure that useProtectedContext is not currently being changed by some
- // other thread.
std::lock_guard lock(mThreadMutex);
- return mRenderEngine->isProtected();
+ return mIsProtected;
}
bool RenderEngineThreaded::supportsProtectedContent() const {
@@ -259,20 +258,28 @@
return mRenderEngine->supportsProtectedContent();
}
-bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
- std::promise<bool> resultPromise;
- std::future<bool> resultFuture = resultPromise.get_future();
+void RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
+ if (isProtected() == useProtectedContext ||
+ (useProtectedContext && !supportsProtectedContent())) {
+ return;
+ }
+
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push(
- [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::useProtectedContext");
- bool returnValue = instance.useProtectedContext(useProtectedContext);
- resultPromise.set_value(returnValue);
- });
+ mFunctionCalls.push([useProtectedContext, this](renderengine::RenderEngine& instance) {
+ ATRACE_NAME("REThreaded::useProtectedContext");
+ instance.useProtectedContext(useProtectedContext);
+ if (instance.isProtected() != useProtectedContext) {
+ ALOGE("Failed to switch RenderEngine context.");
+ // reset the cached mIsProtected value to a good state, but this does not
+ // prevent other callers of this method and isProtected from reading the
+ // invalid cached value.
+ mIsProtected = instance.isProtected();
+ }
+ });
+ mIsProtected = useProtectedContext;
}
mCondition.notify_one();
- return resultFuture.get();
}
void RenderEngineThreaded::cleanupPostRender() {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 9b523b2..f2f5c0f 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -53,7 +53,7 @@
bool isProtected() const override;
bool supportsProtectedContent() const override;
- bool useProtectedContext(bool useProtectedContext) override;
+ void useProtectedContext(bool useProtectedContext) override;
void cleanupPostRender() override;
status_t drawLayers(const DisplaySettings& display,
@@ -100,6 +100,7 @@
* Render Engine
*/
std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
+ std::atomic<bool> mIsProtected = false;
};
} // namespace threaded
} // namespace renderengine
diff --git a/services/gpuservice/bpfprogs/gpu_mem.c b/services/gpuservice/bpfprogs/gpu_mem.c
index c75213b..16e1e8a 100644
--- a/services/gpuservice/bpfprogs/gpu_mem.c
+++ b/services/gpuservice/bpfprogs/gpu_mem.c
@@ -72,4 +72,4 @@
return 0;
}
-char _license[] SEC("license") = "Apache 2.0";
+LICENSE("Apache 2.0");
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index dc0e60c..3d85bef 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -27,7 +27,17 @@
"name": "CtsViewTestCases",
"options": [
{
- "include-filter": "android.view.cts.MotionEventTest"
+ "include-filter": "android.view.cts.MotionEventTest",
+ "include-filter": "android.view.cts.VerifyInputEventTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.VerifiedKeyEventTest",
+ "include-filter": "android.view.VerifiedMotionEventTest"
}
]
},
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index c0010ab..1899c5f 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3787,7 +3787,7 @@
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
- policyFlags |= POLICY_FLAG_FILTERED | POLICY_FLAG_INPUTFILTER_TRUSTED;
+ policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
@@ -4010,16 +4010,14 @@
}
// For all injected events, set device id = VIRTUAL_KEYBOARD_ID. The only exception is events
- // that have gone through the InputFilter. If the event passed through the InputFilter,
- // but did not get modified, assign the provided device id. If the InputFilter modifies the
- // events in any way, it is responsible for removing this flag.
- // If the injected event originated from accessibility, assign the accessibility device id,
- // so that it can be distinguished from regular injected events.
+ // that have gone through the InputFilter. If the event passed through the InputFilter, assign
+ // the provided device id. If the InputFilter is accessibility, and it modifies or synthesizes
+ // the injected event, it is responsible for setting POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY.
+ // For those events, we will set FLAG_IS_ACCESSIBILITY_EVENT to allow apps to distinguish them
+ // from events that originate from actual hardware.
int32_t resolvedDeviceId = VIRTUAL_KEYBOARD_ID;
- if (policyFlags & POLICY_FLAG_INPUTFILTER_TRUSTED) {
+ if (policyFlags & POLICY_FLAG_FILTERED) {
resolvedDeviceId = event->getDeviceId();
- } else if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
- resolvedDeviceId = ACCESSIBILITY_DEVICE_ID;
}
std::queue<std::unique_ptr<EventEntry>> injectedEntries;
@@ -4032,6 +4030,9 @@
}
int32_t flags = incomingKey.getFlags();
+ if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
+ flags |= AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
+ }
int32_t keyCode = incomingKey.getKeyCode();
int32_t metaState = incomingKey.getMetaState();
accelerateMetaShortcuts(resolvedDeviceId, action,
@@ -4073,6 +4074,7 @@
size_t pointerCount = motionEvent.getPointerCount();
const PointerProperties* pointerProperties = motionEvent.getPointerProperties();
int32_t actionButton = motionEvent.getActionButton();
+ int32_t flags = motionEvent.getFlags();
int32_t displayId = motionEvent.getDisplayId();
if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
return InputEventInjectionResult::FAILED;
@@ -4088,6 +4090,10 @@
}
}
+ if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
+ flags |= AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
+ }
+
mLock.lock();
const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
const PointerCoords* samplePointerCoords = motionEvent.getSamplePointerCoords();
@@ -4095,8 +4101,7 @@
std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes,
resolvedDeviceId, motionEvent.getSource(),
motionEvent.getDisplayId(), policyFlags, action,
- actionButton, motionEvent.getFlags(),
- motionEvent.getMetaState(),
+ actionButton, flags, motionEvent.getMetaState(),
motionEvent.getButtonState(),
motionEvent.getClassification(),
motionEvent.getEdgeFlags(),
@@ -4116,7 +4121,7 @@
std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes,
resolvedDeviceId, motionEvent.getSource(),
motionEvent.getDisplayId(), policyFlags,
- action, actionButton, motionEvent.getFlags(),
+ action, actionButton, flags,
motionEvent.getMetaState(),
motionEvent.getButtonState(),
motionEvent.getClassification(),
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 77ca12c..3a9dede 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -3171,7 +3171,8 @@
mWindow->consumeFocusEvent(true);
}
- void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId) {
+ void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
+ int32_t flags) {
KeyEvent event;
const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -3188,6 +3189,45 @@
InputEvent* received = mWindow->consume();
ASSERT_NE(nullptr, received);
ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
+ ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
+ KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
+ ASSERT_EQ(flags, keyEvent.getFlags());
+ }
+
+ void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
+ int32_t flags) {
+ MotionEvent event;
+ PointerProperties pointerProperties[1];
+ PointerCoords pointerCoords[1];
+ pointerProperties[0].clear();
+ pointerProperties[0].id = 0;
+ pointerCoords[0].clear();
+ pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
+ pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
+
+ ui::Transform identityTransform;
+ const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
+ DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
+ AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
+ identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ 0 /*AMOTION_EVENT_INVALID_DISPLAY_SIZE*/,
+ 0 /*AMOTION_EVENT_INVALID_DISPLAY_SIZE*/, eventTime, eventTime,
+ /*pointerCount*/ 1, pointerProperties, pointerCoords);
+
+ const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
+ policyFlags | additionalPolicyFlags));
+
+ InputEvent* received = mWindow->consume();
+ ASSERT_NE(nullptr, received);
+ ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
+ ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
+ MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
+ ASSERT_EQ(flags, motionEvent.getFlags());
}
private:
@@ -3195,20 +3235,29 @@
};
TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
- // We don't need POLICY_FLAG_FILTERED here, but it will be set in practice, so keep it to make
- // the test more closely resemble the real usage
- testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INPUTFILTER_TRUSTED, 3 /*injectedDeviceId*/,
- 3 /*resolvedDeviceId*/);
+ // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
+ // filter. Without it, the event will no different from a regularly injected event, and the
+ // injected device id will be overwritten.
+ testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
+ 0 /*flags*/);
}
-TEST_F(InputFilterInjectionPolicyTest, EventsInjectedFromAccessibility_HaveAccessibilityDeviceId) {
+TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
- 3 /*injectedDeviceId*/, ACCESSIBILITY_DEVICE_ID /*resolvedDeviceId*/);
+ 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
+ AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
+}
+
+TEST_F(InputFilterInjectionPolicyTest,
+ MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
+ testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
+ 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
+ AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
}
TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
- VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/);
+ VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
}
class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index cd3d80e..760c8b9 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -133,6 +133,7 @@
bool mTransformToDisplayInverse{false};
std::shared_ptr<renderengine::ExternalTexture> mBuffer;
+ uint64_t mFrameNumber;
int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
bool mFrameLatencyNeeded{false};
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index c64371b..6b6d434 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -125,11 +125,16 @@
// -----------------------------------------------------------------------
bool BufferQueueLayer::fenceHasSignaled() const {
+ Mutex::Autolock lock(mQueueItemLock);
+
+ if (SurfaceFlinger::enableLatchUnsignaled) {
+ return true;
+ }
+
if (!hasFrameUpdate()) {
return true;
}
- Mutex::Autolock lock(mQueueItemLock);
if (mQueueItems[0].item.mIsDroppable) {
// Even though this buffer's fence may not have signaled yet, it could
// be replaced by another buffer before it has a chance to, which means
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 6b5cf04..645e883 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -44,25 +44,18 @@
using PresentState = frametimeline::SurfaceFrame::PresentState;
namespace {
void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
- const sp<GraphicBuffer>& buffer, const sp<Fence>& releaseFence,
- uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) {
+ const sp<GraphicBuffer>& buffer, uint64_t framenumber,
+ const sp<Fence>& releaseFence, uint32_t transformHint,
+ uint32_t currentMaxAcquiredBufferCount) {
if (!listener) {
return;
}
- listener->onReleaseBuffer(buffer->getId(), releaseFence ? releaseFence : Fence::NO_FENCE,
- transformHint, currentMaxAcquiredBufferCount);
+ listener->onReleaseBuffer({buffer->getId(), framenumber},
+ releaseFence ? releaseFence : Fence::NO_FENCE, transformHint,
+ currentMaxAcquiredBufferCount);
}
} // namespace
-// clang-format off
-const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
-};
-// clang-format on
-
BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
: BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
@@ -75,8 +68,8 @@
// issue with the clone layer trying to use the texture.
if (mBufferInfo.mBuffer != nullptr && !isClone()) {
callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence,
- mTransformHint,
+ mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
+ mBufferInfo.mFence, mTransformHint,
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
mOwnerUid));
}
@@ -87,7 +80,7 @@
if (ch == nullptr) {
return OK;
}
- ch->previousBufferId = mPreviousBufferId;
+ ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;
if (!ch->previousReleaseFence.get()) {
ch->previousReleaseFence = fence;
return OK;
@@ -214,7 +207,7 @@
// see BufferStateLayer::onLayerDisplayed.
for (auto& handle : mDrawingState.callbackHandles) {
if (handle->releasePreviousBuffer) {
- handle->previousBufferId = mPreviousBufferId;
+ handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
break;
}
}
@@ -438,8 +431,8 @@
// dropped and we should decrement the pending buffer count and
// call any release buffer callbacks if set.
callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence,
- mTransformHint,
+ mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
+ mDrawingState.acquireFence, mTransformHint,
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
mOwnerUid));
decrementPendingBufferCount();
@@ -642,6 +635,10 @@
// Interface implementation for BufferLayer
// -----------------------------------------------------------------------
bool BufferStateLayer::fenceHasSignaled() const {
+ if (SurfaceFlinger::enableLatchUnsignaled) {
+ return true;
+ }
+
const bool fenceSignaled =
getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
if (!fenceSignaled) {
@@ -684,7 +681,7 @@
* DeferTransactionUntil -> frameNumber = 2
* Random other stuff
* }
- * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (or mCurrentFrameNumber).
+ * Now imagine mFrameNumber returned mDrawingState.frameNumber (or mCurrentFrameNumber).
* Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we
* haven't swapped mDrawingState to mDrawingState yet we will think the sync point
* is not ready. So we will return false from applyPendingState and not swap
@@ -725,7 +722,7 @@
bool BufferStateLayer::hasFrameUpdate() const {
const State& c(getDrawingState());
- return mDrawingStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
+ return (mDrawingStateModified || mDrawingState.modified) && (c.buffer != nullptr || c.bgColorLayer != nullptr);
}
status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
@@ -792,9 +789,10 @@
decrementPendingBufferCount();
}
- mPreviousBufferId = getCurrentBufferId();
+ mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};
mBufferInfo.mBuffer = s.buffer;
mBufferInfo.mFence = s.acquireFence;
+ mBufferInfo.mFrameNumber = s.frameNumber;
return NO_ERROR;
}
@@ -969,8 +967,8 @@
// then we will drop a buffer and should decrement the pending buffer count and
// call any release buffer callbacks if set.
callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence,
- mTransformHint,
+ mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
+ mDrawingState.acquireFence, mTransformHint,
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
mOwnerUid));
decrementPendingBufferCount();
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 2747018..e567478 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -143,15 +143,8 @@
bool bufferNeedsFiltering() const override;
- static const std::array<float, 16> IDENTITY_MATRIX;
-
- std::unique_ptr<renderengine::Image> mTextureImage;
-
- mutable uint64_t mFrameNumber{0};
- uint64_t mFrameCounter{0};
-
sp<Fence> mPreviousReleaseFence;
- uint64_t mPreviousBufferId = 0;
+ ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
bool mReleasePreviousBuffer = false;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index 29937fb..554e2f4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -24,6 +24,7 @@
#include <compositionengine/LayerFE.h>
#include <compositionengine/OutputColorSetting.h>
#include <math/mat4.h>
+#include <ui/FenceTime.h>
#include <ui/Transform.h>
namespace android::compositionengine {
@@ -83,6 +84,10 @@
// The earliest time to send the present command to the HAL
std::chrono::steady_clock::time_point earliestPresentTime;
+ // The previous present fence. Used together with earliestPresentTime
+ // to prevent an early presentation of a frame.
+ std::shared_ptr<FenceTime> previousPresentFence;
+
// The predicted next invalidation time
std::optional<std::chrono::steady_clock::time_point> nextInvalidateTime;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index d41c2dd..f34cb94 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -19,6 +19,7 @@
#include <cstdint>
#include <math/mat4.h>
+#include <ui/FenceTime.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -118,6 +119,10 @@
// The earliest time to send the present command to the HAL
std::chrono::steady_clock::time_point earliestPresentTime;
+ // The previous present fence. Used together with earliestPresentTime
+ // to prevent an early presentation of a frame.
+ std::shared_ptr<FenceTime> previousPresentFence;
+
// Current display brightness
float displayBrightnessNits{-1.f};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
index 7cb0f6b..2bf931c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -141,7 +141,7 @@
compositionengine::OutputLayer* getBlurLayer() const;
- bool hasHdrLayers() const;
+ bool hasUnsupportedDataspace() const;
bool hasProtectedLayers() const;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index a20d7b3..bce438f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -242,13 +242,6 @@
ui::Dataspace getDataspace() const { return mOutputDataspace.get(); }
- bool isHdr() const {
- const ui::Dataspace transfer =
- static_cast<ui::Dataspace>(getDataspace() & ui::Dataspace::TRANSFER_MASK);
- return (transfer == ui::Dataspace::TRANSFER_ST2084 ||
- transfer == ui::Dataspace::TRANSFER_HLG);
- }
-
bool isProtected() const {
return getOutputLayer()->getLayerFE().getCompositionState()->hasProtectedContent;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index ae1336e..2f2c686 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -229,7 +229,8 @@
auto& hwc = getCompositionEngine().getHwComposer();
if (status_t result =
hwc.getDeviceCompositionChanges(*halDisplayId, anyLayersRequireClientComposition(),
- getState().earliestPresentTime, &changes);
+ getState().earliestPresentTime,
+ getState().previousPresentFence, &changes);
result != NO_ERROR) {
ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
strerror(-result));
@@ -330,7 +331,8 @@
}
auto& hwc = getCompositionEngine().getHwComposer();
- hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime);
+ hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime,
+ getState().previousPresentFence);
fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 67bb149..cafcb40 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -729,6 +729,7 @@
}
editState().earliestPresentTime = refreshArgs.earliestPresentTime;
+ editState().previousPresentFence = refreshArgs.previousPresentFence;
compositionengine::OutputLayer* peekThroughLayer = nullptr;
sp<GraphicBuffer> previousOverride = nullptr;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index e4e46a7..56e9d27 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -216,8 +216,18 @@
// reduce uses a FloatRect to provide more accuracy during the
// transformation. We then round upon constructing 'frame'.
- Rect frame{
- layerTransform.transform(reduce(layerState.geomLayerBounds, activeTransparentRegion))};
+ FloatRect geomLayerBounds = layerState.geomLayerBounds;
+
+ // Some HWCs may clip client composited input to its displayFrame. Make sure
+ // that this does not cut off the shadow.
+ if (layerState.forceClientComposition && layerState.shadowRadius > 0.0f) {
+ const auto outset = layerState.shadowRadius;
+ geomLayerBounds.left -= outset;
+ geomLayerBounds.top -= outset;
+ geomLayerBounds.right += outset;
+ geomLayerBounds.bottom += outset;
+ }
+ Rect frame{layerTransform.transform(reduce(geomLayerBounds, activeTransparentRegion))};
if (!frame.intersect(outputState.layerStackSpace.content, &frame)) {
frame.clear();
}
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index 22d9dc6..b24274e 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -295,9 +295,7 @@
return false;
}
- // Do not use a hole punch with an HDR layer; this should be done in client
- // composition to properly mix HDR with SDR.
- if (hasHdrLayers()) {
+ if (hasUnsupportedDataspace()) {
return false;
}
@@ -352,9 +350,22 @@
return mBlurLayer ? mBlurLayer->getOutputLayer() : nullptr;
}
-bool CachedSet::hasHdrLayers() const {
- return std::any_of(mLayers.cbegin(), mLayers.cend(),
- [](const Layer& layer) { return layer.getState()->isHdr(); });
+bool CachedSet::hasUnsupportedDataspace() const {
+ return std::any_of(mLayers.cbegin(), mLayers.cend(), [](const Layer& layer) {
+ auto dataspace = layer.getState()->getDataspace();
+ const auto transfer = static_cast<ui::Dataspace>(dataspace & ui::Dataspace::TRANSFER_MASK);
+ if (transfer == ui::Dataspace::TRANSFER_ST2084 || transfer == ui::Dataspace::TRANSFER_HLG) {
+ // Skip HDR.
+ return true;
+ }
+
+ if ((dataspace & HAL_DATASPACE_STANDARD_MASK) == HAL_DATASPACE_STANDARD_BT601_625) {
+ // RenderEngine does not match some DPUs, so skip
+ // to avoid flickering/color differences.
+ return true;
+ }
+ return false;
+ });
}
bool CachedSet::hasProtectedLayers() const {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 153cee3..f033279 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -420,7 +420,7 @@
const bool layerIsInactive = now - currentSet->getLastUpdate() > mActiveLayerTimeout;
const bool layerHasBlur = currentSet->hasBlurBehind();
if (layerIsInactive && (firstLayer || runHasFirstLayer || !layerHasBlur) &&
- !currentSet->hasHdrLayers()) {
+ !currentSet->hasUnsupportedDataspace()) {
if (isPartOfRun) {
builder.append(currentSet->getLayerCount());
} else {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index db9437b..c037cc6 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -579,7 +579,7 @@
TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutOnHwcError) {
EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()).WillOnce(Return(false));
EXPECT_CALL(mHwComposer,
- getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _))
+ getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _))
.WillOnce(Return(INVALID_OPERATION));
mDisplay->chooseCompositionStrategy();
@@ -602,7 +602,7 @@
.WillOnce(Return(false));
EXPECT_CALL(mHwComposer,
- getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _))
+ getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _))
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
@@ -633,8 +633,8 @@
.WillOnce(Return(false));
EXPECT_CALL(mHwComposer,
- getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _))
- .WillOnce(DoAll(SetArgPointee<3>(changes), Return(NO_ERROR)));
+ getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(changes), Return(NO_ERROR)));
EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1);
EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1);
EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1);
@@ -844,7 +844,7 @@
sp<Fence> layer1Fence = new Fence();
sp<Fence> layer2Fence = new Fence();
- EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(HalDisplayId(DEFAULT_DISPLAY_ID), _))
+ EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(HalDisplayId(DEFAULT_DISPLAY_ID), _, _))
.Times(1);
EXPECT_CALL(mHwComposer, getPresentFence(HalDisplayId(DEFAULT_DISPLAY_ID)))
.WillOnce(Return(presentFence));
@@ -1020,7 +1020,7 @@
mDisplay->editState().isEnabled = true;
- EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(_, _));
+ EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(_, _, _));
EXPECT_CALL(*mDisplaySurface, onFrameCommitted());
mDisplay->postFramebuffer();
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 64cbea9..a195e58 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -52,14 +52,16 @@
std::optional<PhysicalDisplayId>));
MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId));
MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId));
- MOCK_METHOD4(getDeviceCompositionChanges,
+ MOCK_METHOD5(getDeviceCompositionChanges,
status_t(HalDisplayId, bool, std::chrono::steady_clock::time_point,
+ const std::shared_ptr<FenceTime>&,
std::optional<android::HWComposer::DeviceRequestedChanges>*));
MOCK_METHOD5(setClientTarget,
status_t(HalDisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
ui::Dataspace));
- MOCK_METHOD2(presentAndGetReleaseFences,
- status_t(HalDisplayId, std::chrono::steady_clock::time_point));
+ MOCK_METHOD3(presentAndGetReleaseFences,
+ status_t(HalDisplayId, std::chrono::steady_clock::time_point,
+ const std::shared_ptr<FenceTime>&));
MOCK_METHOD2(setPowerMode, status_t(PhysicalDisplayId, hal::PowerMode));
MOCK_METHOD2(setActiveConfig, status_t(HalDisplayId, size_t));
MOCK_METHOD2(setColorTransform, status_t(HalDisplayId, const mat4&));
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index b738096..fc8cb50 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -29,8 +29,10 @@
PowerAdvisor();
~PowerAdvisor() override;
+ MOCK_METHOD0(init, void());
MOCK_METHOD0(onBootFinished, void());
MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+ MOCK_METHOD0(isUsingExpensiveRendering, bool());
MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index e9ecf3e..c8c6012 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -324,6 +324,27 @@
EXPECT_THAT(calculateOutputDisplayFrame(), expected);
}
+TEST_F(OutputLayerDisplayFrameTest, shadowExpandsDisplayFrame) {
+ const int kShadowRadius = 5;
+ mLayerFEState.shadowRadius = kShadowRadius;
+ mLayerFEState.forceClientComposition = true;
+
+ mLayerFEState.geomLayerBounds = FloatRect{100.f, 100.f, 200.f, 200.f};
+ Rect expected{mLayerFEState.geomLayerBounds};
+ expected.inset(-kShadowRadius, -kShadowRadius, -kShadowRadius, -kShadowRadius);
+ EXPECT_THAT(calculateOutputDisplayFrame(), expected);
+}
+
+TEST_F(OutputLayerDisplayFrameTest, shadowExpandsDisplayFrame_onlyIfForcingClientComposition) {
+ const int kShadowRadius = 5;
+ mLayerFEState.shadowRadius = kShadowRadius;
+ mLayerFEState.forceClientComposition = false;
+
+ mLayerFEState.geomLayerBounds = FloatRect{100.f, 100.f, 200.f, 200.f};
+ Rect expected{mLayerFEState.geomLayerBounds};
+ EXPECT_THAT(calculateOutputDisplayFrame(), expected);
+}
+
/*
* OutputLayer::calculateOutputRelativeBufferTransform()
*/
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 742b155..ee73cfc 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3487,7 +3487,7 @@
mLayer2.mLayerFEState.hasProtectedContent = true;
EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
- EXPECT_CALL(mRenderEngine, useProtectedContext(false)).WillOnce(Return(true));
+ EXPECT_CALL(mRenderEngine, useProtectedContext(false));
mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 0acc317..7f0e186 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -457,6 +457,20 @@
EXPECT_FALSE(cachedSet.requiresHolePunch());
}
+TEST_F(CachedSetTest, holePunch_requiresNonBT601_625) {
+ mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625;
+ mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
+
+ CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
+ mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
+
+ CachedSet cachedSet(layer);
+ EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
+
+ EXPECT_FALSE(cachedSet.requiresHolePunch());
+}
+
TEST_F(CachedSetTest, requiresHolePunch) {
CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 334b855..f5cfd2f 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -937,5 +937,152 @@
(kCachedSetRenderDuration + 10ms));
}
+TEST_F(FlattenerTest, flattenLayers_skipsBT601_625) {
+ auto& layerState1 = mTestLayers[0]->layerState;
+ const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+
+ auto& layerState2 = mTestLayers[1]->layerState;
+ const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
+
+ // The third layer uses a dataspace that will not be flattened due to
+ // possible mismatch with DPU rendering.
+ auto& layerState3 = mTestLayers[2]->layerState;
+ const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
+ mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625;
+ mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
+
+ const std::vector<const LayerState*> layers = {
+ layerState1.get(),
+ layerState2.get(),
+ layerState3.get(),
+ };
+
+ initializeFlattener(layers);
+
+ mTime += 200ms;
+ initializeOverrideBuffer(layers);
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+
+ // This will render a CachedSet.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ // We've rendered a CachedSet, but we haven't merged it in.
+ EXPECT_EQ(nullptr, overrideBuffer1);
+ EXPECT_EQ(nullptr, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+
+ // This time we merge the CachedSet in, so we have a new hash, and we should
+ // only have two sets.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0);
+ initializeOverrideBuffer(layers);
+ EXPECT_NE(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ EXPECT_NE(nullptr, overrideBuffer1);
+ EXPECT_EQ(overrideBuffer1, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+}
+
+TEST_F(FlattenerTest, flattenLayers_skipsHDR) {
+ auto& layerState1 = mTestLayers[0]->layerState;
+ const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+
+ auto& layerState2 = mTestLayers[1]->layerState;
+ const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
+
+ // The third layer uses a dataspace that will not be flattened due to
+ // possible mismatch with DPU rendering.
+ auto& layerState3 = mTestLayers[2]->layerState;
+ const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
+ mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_ITU_HLG;
+ mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
+
+ const std::vector<const LayerState*> layers = {
+ layerState1.get(),
+ layerState2.get(),
+ layerState3.get(),
+ };
+
+ initializeFlattener(layers);
+
+ mTime += 200ms;
+ initializeOverrideBuffer(layers);
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+
+ // This will render a CachedSet.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ // We've rendered a CachedSet, but we haven't merged it in.
+ EXPECT_EQ(nullptr, overrideBuffer1);
+ EXPECT_EQ(nullptr, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+
+ // This time we merge the CachedSet in, so we have a new hash, and we should
+ // only have two sets.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0);
+ initializeOverrideBuffer(layers);
+ EXPECT_NE(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ EXPECT_NE(nullptr, overrideBuffer1);
+ EXPECT_EQ(overrideBuffer1, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+}
+
+TEST_F(FlattenerTest, flattenLayers_skipsHDR2) {
+ auto& layerState1 = mTestLayers[0]->layerState;
+ const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+
+ auto& layerState2 = mTestLayers[1]->layerState;
+ const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
+
+ // The third layer uses a dataspace that will not be flattened due to
+ // possible mismatch with DPU rendering.
+ auto& layerState3 = mTestLayers[2]->layerState;
+ const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
+ mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_PQ;
+ mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
+
+ const std::vector<const LayerState*> layers = {
+ layerState1.get(),
+ layerState2.get(),
+ layerState3.get(),
+ };
+
+ initializeFlattener(layers);
+
+ mTime += 200ms;
+ initializeOverrideBuffer(layers);
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+
+ // This will render a CachedSet.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ // We've rendered a CachedSet, but we haven't merged it in.
+ EXPECT_EQ(nullptr, overrideBuffer1);
+ EXPECT_EQ(nullptr, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+
+ // This time we merge the CachedSet in, so we have a new hash, and we should
+ // only have two sets.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0);
+ initializeOverrideBuffer(layers);
+ EXPECT_NE(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ EXPECT_NE(nullptr, overrideBuffer1);
+ EXPECT_EQ(overrideBuffer1, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 32f04e5..7e45dab 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -471,6 +471,7 @@
status_t HWComposer::getDeviceCompositionChanges(
HalDisplayId displayId, bool frameUsesClientComposition,
std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence,
std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
ATRACE_CALL();
@@ -487,12 +488,16 @@
hal::Error error = hal::Error::NONE;
- // First try to skip validate altogether when we passed the earliest time
- // to present and there is no client. Otherwise, we may present a frame too
- // early or in case of client composition we first need to render the
+ // First try to skip validate altogether. We can do that when
+ // 1. The previous frame has not been presented yet or already passed the
+ // earliest time to present. Otherwise, we may present a frame too early.
+ // 2. There is no client composition. Otherwise, we first need to render the
// client target buffer.
- const bool canSkipValidate =
- std::chrono::steady_clock::now() >= earliestPresentTime && !frameUsesClientComposition;
+ const bool prevFencePending =
+ previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
+ const bool canPresentEarly =
+ !prevFencePending && std::chrono::steady_clock::now() < earliestPresentTime;
+ const bool canSkipValidate = !canPresentEarly && !frameUsesClientComposition;
displayData.validateWasSkipped = false;
if (canSkipValidate) {
sp<Fence> outPresentFence;
@@ -559,7 +564,8 @@
}
status_t HWComposer::presentAndGetReleaseFences(
- HalDisplayId displayId, std::chrono::steady_clock::time_point earliestPresentTime) {
+ HalDisplayId displayId, std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence) {
ATRACE_CALL();
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -575,7 +581,9 @@
return NO_ERROR;
}
- {
+ const bool previousFramePending =
+ previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
+ if (!previousFramePending) {
ATRACE_NAME("wait for earliest present time");
std::this_thread::sleep_until(earliestPresentTime);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index cd6f9f5..b1849e8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -27,7 +27,7 @@
#include <vector>
#include <android-base/thread_annotations.h>
-#include <ui/Fence.h>
+#include <ui/FenceTime.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -134,6 +134,7 @@
virtual status_t getDeviceCompositionChanges(
HalDisplayId, bool frameUsesClientComposition,
std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence,
std::optional<DeviceRequestedChanges>* outChanges) = 0;
virtual status_t setClientTarget(HalDisplayId, uint32_t slot, const sp<Fence>& acquireFence,
@@ -141,7 +142,8 @@
// Present layers to the display and read releaseFences.
virtual status_t presentAndGetReleaseFences(
- HalDisplayId, std::chrono::steady_clock::time_point earliestPresentTime) = 0;
+ HalDisplayId, std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence) = 0;
// set power mode
virtual status_t setPowerMode(PhysicalDisplayId, hal::PowerMode) = 0;
@@ -275,6 +277,7 @@
status_t getDeviceCompositionChanges(
HalDisplayId, bool frameUsesClientComposition,
std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence,
std::optional<DeviceRequestedChanges>* outChanges) override;
status_t setClientTarget(HalDisplayId, uint32_t slot, const sp<Fence>& acquireFence,
@@ -282,7 +285,8 @@
// Present layers to the display and read releaseFences.
status_t presentAndGetReleaseFences(
- HalDisplayId, std::chrono::steady_clock::time_point earliestPresentTime) override;
+ HalDisplayId, std::chrono::steady_clock::time_point earliestPresentTime,
+ const std::shared_ptr<FenceTime>& previousPresentFence) override;
// set power mode
status_t setPowerMode(PhysicalDisplayId, hal::PowerMode mode) override;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 901e19a..1765caf 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -32,6 +32,7 @@
#include "../SurfaceFlingerProperties.h"
#include "PowerAdvisor.h"
+#include "SurfaceFlinger.h"
namespace android {
namespace Hwc2 {
@@ -61,14 +62,22 @@
} // namespace
-PowerAdvisor::PowerAdvisor()
- : mUseUpdateImminentTimer(getUpdateTimeout() > 0),
- mUpdateImminentTimer(
+PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
+ : mFlinger(flinger),
+ mUseScreenUpdateTimer(getUpdateTimeout() > 0),
+ mScreenUpdateTimer(
"UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
/* resetCallback */ [this] { mSendUpdateImminent.store(false); },
- /* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
- if (mUseUpdateImminentTimer) {
- mUpdateImminentTimer.start();
+ /* timeoutCallback */
+ [this] {
+ mSendUpdateImminent.store(true);
+ mFlinger.disableExpensiveRendering();
+ }) {}
+
+void PowerAdvisor::init() {
+ // Defer starting the screen update timer until SurfaceFlinger finishes construction.
+ if (mUseScreenUpdateTimer) {
+ mScreenUpdateTimer.start();
}
}
@@ -122,8 +131,8 @@
}
}
- if (mUseUpdateImminentTimer) {
- mUpdateImminentTimer.reset();
+ if (mUseScreenUpdateTimer) {
+ mScreenUpdateTimer.reset();
}
}
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 95eb0e2..f2d0766 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -25,14 +25,20 @@
#include "DisplayIdentification.h"
namespace android {
+
+class SurfaceFlinger;
+
namespace Hwc2 {
class PowerAdvisor {
public:
virtual ~PowerAdvisor();
+ // Initializes resources that cannot be initialized on construction
+ virtual void init() = 0;
virtual void onBootFinished() = 0;
virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
+ virtual bool isUsingExpensiveRendering() = 0;
virtual void notifyDisplayUpdateImminent() = 0;
};
@@ -50,11 +56,13 @@
virtual bool notifyDisplayUpdateImminent() = 0;
};
- PowerAdvisor();
+ PowerAdvisor(SurfaceFlinger& flinger);
~PowerAdvisor() override;
+ void init() override;
void onBootFinished() override;
void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
+ bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; }
void notifyDisplayUpdateImminent() override;
private:
@@ -67,9 +75,10 @@
std::unordered_set<DisplayId> mExpensiveDisplays;
bool mNotifiedExpensiveRendering = false;
- const bool mUseUpdateImminentTimer;
+ SurfaceFlinger& mFlinger;
+ const bool mUseScreenUpdateTimer;
std::atomic_bool mSendUpdateImminent = true;
- scheduler::OneShotTimer mUpdateImminentTimer;
+ scheduler::OneShotTimer mScreenUpdateTimer;
};
} // namespace impl
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 15ecf13..139f91f 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -96,7 +96,7 @@
// The various thresholds for App and SF. If the actual timestamp falls within the threshold
// compared to prediction, we treat it as on time.
nsecs_t presentThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
- nsecs_t deadlineThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
+ nsecs_t deadlineThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(0ms).count();
nsecs_t startThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ad31b3f..00e0432 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -177,6 +177,9 @@
if (mDrawingState.sidebandStream != nullptr) {
mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
}
+ if (mHadClonedChild) {
+ mFlinger->mNumClones--;
+ }
}
LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
@@ -254,6 +257,7 @@
if (mRemovedFromDrawingState) {
mRemovedFromDrawingState = false;
mFlinger->mScheduler->registerLayer(this);
+ mFlinger->removeFromOffscreenLayers(this);
}
for (const auto& child : mCurrentChildren) {
@@ -2535,6 +2539,12 @@
return parent == nullptr ? false : parent->getPrimaryDisplayOnly();
}
+void Layer::setClonedChild(const sp<Layer>& clonedChild) {
+ mClonedChild = clonedChild;
+ mHadClonedChild = true;
+ mFlinger->mNumClones++;
+}
+
// ---------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ec9bb7c..e726d37 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -863,6 +863,8 @@
// The layers in the cloned hierarchy will match the lifetime of the real layers. That is
// if the real layer is destroyed, then the clone layer will also be destroyed.
sp<Layer> mClonedChild;
+ bool mHadClonedChild = false;
+ void setClonedChild(const sp<Layer>& mClonedChild);
mutable bool contentDirty{false};
Region surfaceDamageRegion;
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 653aca6..aa2fec5 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -287,33 +287,12 @@
descriptors.emplace_back(descriptor);
}
- auto dx = 0;
- auto dy = 0;
- switch (orientation) {
- case ui::Transform::ROT_90:
- dx = displaySize.getWidth();
- break;
- case ui::Transform::ROT_180:
- dx = displaySize.getWidth();
- dy = displaySize.getHeight();
- break;
- case ui::Transform::ROT_270:
- dy = displaySize.getHeight();
- break;
- default:
- break;
- }
-
- ui::Transform t(orientation);
- auto screencapRegion = t.transform(sampleRegion);
- screencapRegion = screencapRegion.translate(dx, dy);
-
const Rect sampledBounds = sampleRegion.bounds();
+ constexpr bool kUseIdentityTransform = false;
SurfaceFlinger::RenderAreaFuture renderAreaFuture = ftl::defer([=] {
- return DisplayRenderArea::create(displayWeak, screencapRegion.bounds(),
- sampledBounds.getSize(), ui::Dataspace::V0_SRGB,
- orientation);
+ return DisplayRenderArea::create(displayWeak, sampledBounds, sampledBounds.getSize(),
+ ui::Dataspace::V0_SRGB, kUseIdentityTransform);
});
std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 4f47ed8..0334d70 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -889,6 +889,7 @@
const auto& deviceMin = *mMinSupportedRefreshRate;
const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();
+ const auto& currentPolicy = getCurrentPolicyLocked();
// Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
// the min allowed refresh rate is higher than the device min, we do not want to enable the
@@ -897,6 +898,10 @@
return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
}
if (minByPolicy == maxByPolicy) {
+ // when min primary range in display manager policy is below device min turn on the timer.
+ if (currentPolicy->primaryRange.min.lessThanWithMargin(deviceMin.getFps())) {
+ return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
+ }
return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
}
// Turn on the timer in all other cases.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 0358e8c..dfd1395 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -326,8 +326,7 @@
return mRefreshRates.size() > 1;
}
- // Class to enumerate options around toggling the kernel timer on and off. We have an option
- // for no change to avoid extra calls to kernel.
+ // Class to enumerate options around toggling the kernel timer on and off.
enum class KernelIdleTimerAction {
TurnOff, // Turn off the idle timer.
TurnOn // Turn on the idle timer.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e2f3ebb..0c23dc1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -310,6 +310,7 @@
ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
bool SurfaceFlinger::useFrameRateApi;
bool SurfaceFlinger::enableSdrDimming;
+bool SurfaceFlinger::enableLatchUnsignaled;
std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) {
switch(displayColorSetting) {
@@ -344,7 +345,8 @@
mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
- mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {
+ mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
+ mPowerAdvisor(*this) {
ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); });
@@ -479,6 +481,8 @@
// Debug property overrides ro. property
enableSdrDimming = property_get_bool("debug.sf.enable_sdr_dimming", enable_sdr_dimming(false));
+
+ enableLatchUnsignaled = base::GetBoolProperty("debug.sf.latch_unsignaled"s, false);
}
SurfaceFlinger::~SurfaceFlinger() = default;
@@ -816,6 +820,8 @@
// set initial conditions (e.g. unblank default device)
initializeDisplays();
+ mPowerAdvisor.init();
+
char primeShaderCache[PROPERTY_VALUE_MAX];
property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
if (atoi(primeShaderCache)) {
@@ -1183,6 +1189,10 @@
updatePhaseConfiguration(refreshRate);
ATRACE_INT("ActiveConfigFPS", refreshRate.getValue());
+ if (mRefreshRateOverlay) {
+ mRefreshRateOverlay->changeRefreshRate(upcomingMode->getFps());
+ }
+
if (mUpcomingActiveMode.event != Scheduler::ModeEvent::None) {
const nsecs_t vsyncPeriod = refreshRate.getPeriodNsecs();
const auto physicalId = display->getPhysicalId();
@@ -1265,14 +1275,24 @@
}
mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
- if (mRefreshRateOverlay) {
- mRefreshRateOverlay->changeRefreshRate(desiredMode->getFps());
- }
// Scheduler will submit an empty frame to HWC if needed.
mSetActiveModePending = true;
}
+void SurfaceFlinger::disableExpensiveRendering() {
+ schedule([=]() MAIN_THREAD {
+ ATRACE_CALL();
+ if (mPowerAdvisor.isUsingExpensiveRendering()) {
+ const auto& displays = ON_MAIN_THREAD(mDisplays);
+ for (const auto& [_, display] : displays) {
+ const static constexpr auto kDisable = false;
+ mPowerAdvisor.setExpensiveRenderingExpected(display->getId(), kDisable);
+ }
+ }
+ }).wait();
+}
+
std::vector<ColorMode> SurfaceFlinger::getDisplayColorModes(PhysicalDisplayId displayId) {
auto modes = getHwComposer().getColorModes(displayId);
bool isInternalDisplay = displayId == getInternalDisplayIdLocked();
@@ -2070,6 +2090,7 @@
const auto prevVsyncTime = mScheduler->getPreviousVsyncFrom(mExpectedPresentTime);
const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration;
+ refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime;
refreshArgs.nextInvalidateTime = mEventQueue->nextExpectedInvalidate();
mGeometryInvalid = false;
@@ -3233,19 +3254,10 @@
}
}
- // TODO(b/163019109): See if this traversal is needed at all...
- if (!mOffscreenLayers.empty()) {
- mDrawingState.traverse([&](Layer* layer) {
- // If the layer can be reached when traversing mDrawingState, then the layer is no
- // longer offscreen. Remove the layer from the offscreenLayer set.
- if (mOffscreenLayers.count(layer)) {
- mOffscreenLayers.erase(layer);
- }
- });
- }
-
commitOffscreenLayers();
- mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
+ if (mNumClones > 0) {
+ mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
+ }
}
void SurfaceFlinger::commitOffscreenLayers() {
@@ -3351,7 +3363,9 @@
mBootStage = BootStage::BOOTANIMATION;
}
- mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
+ if (mNumClones > 0) {
+ mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
+ }
// Only continue with the refresh if there is actually new work to do
return !mLayersWithQueuedFrames.empty() && newDataLatched;
@@ -3571,7 +3585,7 @@
for (const ComposerState& state : states) {
const layer_state_t& s = state.state;
const bool acquireFenceChanged = (s.what & layer_state_t::eAcquireFenceChanged);
- if (acquireFenceChanged && s.acquireFence &&
+ if (acquireFenceChanged && s.acquireFence && !enableLatchUnsignaled &&
s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
ATRACE_NAME("fence unsignaled");
return false;
@@ -4236,7 +4250,7 @@
return result;
}
- mirrorLayer->mClonedChild = mirrorFrom->createClone();
+ mirrorLayer->setClonedChild(mirrorFrom->createClone());
}
*outLayerId = mirrorLayer->sequence;
@@ -6602,7 +6616,7 @@
void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
mNumLayers--;
- removeFromOffscreenLayers(layer);
+ removeHierarchyFromOffscreenLayers(layer);
if (!layer->isRemovedFromCurrentState()) {
mScheduler->deregisterLayer(layer);
}
@@ -6615,13 +6629,17 @@
// from dangling children layers such that they are not reachable from the
// Drawing state nor the offscreen layer list
// See b/141111965
-void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) {
+void SurfaceFlinger::removeHierarchyFromOffscreenLayers(Layer* layer) {
for (auto& child : layer->getCurrentChildren()) {
mOffscreenLayers.emplace(child.get());
}
mOffscreenLayers.erase(layer);
}
+void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) {
+ mOffscreenLayers.erase(layer);
+}
+
status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ,
float lightRadius) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f33df86..b9b26db 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -270,6 +270,8 @@
// being treated as native display brightness
static bool enableSdrDimming;
+ static bool enableLatchUnsignaled;
+
// must be called before clients can connect
void init() ANDROID_API;
@@ -311,8 +313,12 @@
void onLayerFirstRef(Layer*);
void onLayerDestroyed(Layer*);
+ void removeHierarchyFromOffscreenLayers(Layer* layer);
void removeFromOffscreenLayers(Layer* layer);
+ // TODO: Remove atomic if move dtor to main thread CL lands
+ std::atomic<uint32_t> mNumClones;
+
TransactionCallbackInvoker& getTransactionCallbackInvoker() {
return mTransactionCallbackInvoker;
}
@@ -329,6 +335,10 @@
bool mDisableClientCompositionCache = false;
void setInputWindowsFinished();
+ // Disables expensive rendering for all displays
+ // This is scheduled on the main thread
+ void disableExpensiveRendering();
+
protected:
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index fdf16a7..6af69f0 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -237,7 +237,8 @@
handle->previousReleaseFence,
handle->transformHint,
handle->currentMaxAcquiredBufferCount,
- eventStats, jankData, handle->previousBufferId);
+ eventStats, jankData,
+ handle->previousReleaseCallbackId);
}
return NO_ERROR;
}
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 444bec6..6f4d812 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -51,7 +51,7 @@
nsecs_t refreshStartTime = 0;
nsecs_t dequeueReadyTime = 0;
uint64_t frameNumber = 0;
- uint64_t previousBufferId = 0;
+ ReleaseCallbackId previousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
};
class TransactionCallbackInvoker {
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index 5aa809d..579a26e 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -29,7 +29,7 @@
// b/181132765 - disabled until cuttlefish failures are investigated
class ReleaseBufferCallbackHelper {
public:
- static void function(void* callbackContext, uint64_t graphicsBufferId,
+ static void function(void* callbackContext, ReleaseCallbackId callbackId,
const sp<Fence>& releaseFence,
uint32_t /*currentMaxAcquiredBufferCount*/) {
if (!callbackContext) {
@@ -38,11 +38,11 @@
ReleaseBufferCallbackHelper* helper =
static_cast<ReleaseBufferCallbackHelper*>(callbackContext);
std::lock_guard lock(helper->mMutex);
- helper->mCallbackDataQueue.emplace(graphicsBufferId, releaseFence);
+ helper->mCallbackDataQueue.emplace(callbackId, releaseFence);
helper->mConditionVariable.notify_all();
}
- void getCallbackData(uint64_t* bufferId) {
+ void getCallbackData(ReleaseCallbackId* callbackId) {
std::unique_lock lock(mMutex);
if (mCallbackDataQueue.empty()) {
if (!mConditionVariable.wait_for(lock, std::chrono::seconds(3),
@@ -53,7 +53,7 @@
auto callbackData = mCallbackDataQueue.front();
mCallbackDataQueue.pop();
- *bufferId = callbackData.first;
+ *callbackId = callbackData.first;
}
void verifyNoCallbacks() {
@@ -72,7 +72,7 @@
std::mutex mMutex;
std::condition_variable mConditionVariable;
- std::queue<std::pair<uint64_t, sp<Fence>>> mCallbackDataQueue;
+ std::queue<std::pair<ReleaseCallbackId, sp<Fence>>> mCallbackDataQueue;
};
class ReleaseBufferCallbackTest : public LayerTransactionTest {
@@ -82,10 +82,11 @@
}
static void submitBuffer(const sp<SurfaceControl>& layer, sp<GraphicBuffer> buffer,
- sp<Fence> fence, CallbackHelper& callback,
+ sp<Fence> fence, CallbackHelper& callback, const ReleaseCallbackId& id,
ReleaseBufferCallbackHelper& releaseCallback) {
Transaction t;
- t.setBuffer(layer, buffer, releaseCallback.getCallback());
+ t.setFrameNumber(layer, id.framenumber);
+ t.setBuffer(layer, buffer, id, releaseCallback.getCallback());
t.setAcquireFence(layer, fence);
t.addTransactionCompletedCallback(callback.function, callback.getContext());
t.apply();
@@ -98,10 +99,10 @@
}
static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback,
- uint64_t expectedReleaseBufferId) {
- uint64_t actualReleaseBufferId;
+ const ReleaseCallbackId& expectedCallbackId) {
+ ReleaseCallbackId actualReleaseBufferId;
releaseCallback.getCallbackData(&actualReleaseBufferId);
- EXPECT_EQ(expectedReleaseBufferId, actualReleaseBufferId);
+ EXPECT_EQ(expectedCallbackId, actualReleaseBufferId);
releaseCallback.verifyNoCallbacks();
}
static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() {
@@ -116,6 +117,10 @@
BufferUsage::COMPOSER_OVERLAY,
"test");
}
+ static uint64_t generateFrameNumber() {
+ static uint64_t sFrameNumber = 0;
+ return ++sFrameNumber;
+ }
};
TEST_F(ReleaseBufferCallbackTest, DISABLED_PresentBuffer) {
@@ -125,7 +130,9 @@
// If a buffer is being presented, we should not emit a release callback.
sp<GraphicBuffer> firstBuffer = getBuffer();
- submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, firstBufferCallbackId,
+ *releaseCallback);
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
ExpectedResult::Buffer::NOT_ACQUIRED);
@@ -143,13 +150,15 @@
// If a presented buffer is replaced, we should emit a release callback for the
// previously presented buffer.
sp<GraphicBuffer> secondBuffer = getBuffer();
- submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
+ ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, secondBufferCallbackId,
+ *releaseCallback);
expected = ExpectedResult();
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
ExpectedResult::Buffer::NOT_ACQUIRED,
ExpectedResult::PreviousBuffer::RELEASED);
ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
- ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
}
TEST_F(ReleaseBufferCallbackTest, DISABLED_OffScreenLayer) {
@@ -160,7 +169,9 @@
// If a buffer is being presented, we should not emit a release callback.
sp<GraphicBuffer> firstBuffer = getBuffer();
- submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, firstBufferCallbackId,
+ *releaseCallback);
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
ExpectedResult::Buffer::NOT_ACQUIRED);
@@ -184,23 +195,27 @@
// If a presented buffer is replaced, we should emit a release callback for the
// previously presented buffer.
sp<GraphicBuffer> secondBuffer = getBuffer();
- submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
+ ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, secondBufferCallbackId,
+ *releaseCallback);
expected = ExpectedResult();
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
ExpectedResult::Buffer::NOT_ACQUIRED,
ExpectedResult::PreviousBuffer::NOT_RELEASED);
ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
- ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
// If continue to submit buffer we continue to get release callbacks
sp<GraphicBuffer> thirdBuffer = getBuffer();
- submitBuffer(layer, thirdBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
+ ReleaseCallbackId thirdBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, thirdBuffer, Fence::NO_FENCE, transactionCallback, thirdBufferCallbackId,
+ *releaseCallback);
expected = ExpectedResult();
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
ExpectedResult::Buffer::NOT_ACQUIRED,
ExpectedResult::PreviousBuffer::NOT_RELEASED);
ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
- ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBuffer->getId()));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBufferCallbackId));
}
TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_layerdestroy) {
@@ -210,7 +225,9 @@
// If a buffer is being presented, we should not emit a release callback.
sp<GraphicBuffer> firstBuffer = getBuffer();
- submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback);
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, firstBufferCallbackId,
+ *releaseCallback);
{
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
@@ -225,7 +242,7 @@
t.apply();
layer = nullptr;
- ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
}
// Destroying a never presented layer emits a callback.
@@ -242,7 +259,9 @@
// Submitting a buffer does not emit a callback.
sp<GraphicBuffer> firstBuffer = getBuffer();
- submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback);
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, firstBufferCallbackId,
+ *releaseCallback);
{
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
@@ -253,19 +272,21 @@
// Submitting a second buffer will replace the drawing state buffer and emit a callback.
sp<GraphicBuffer> secondBuffer = getBuffer();
- submitBuffer(layer, secondBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback);
+ ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+ submitBuffer(layer, secondBuffer, Fence::NO_FENCE, *transactionCallback, secondBufferCallbackId,
+ *releaseCallback);
{
ExpectedResult expected;
expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
ExpectedResult::Buffer::NOT_ACQUIRED);
ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
ASSERT_NO_FATAL_FAILURE(
- waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
+ waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
}
// Destroying the offscreen layer emits a callback.
layer = nullptr;
- ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBuffer->getId()));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBufferCallbackId));
}
TEST_F(ReleaseBufferCallbackTest, DISABLED_FrameDropping) {
@@ -275,12 +296,13 @@
// If a buffer is being presented, we should not emit a release callback.
sp<GraphicBuffer> firstBuffer = getBuffer();
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
// Try to present 100ms in the future
nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
Transaction t;
- t.setBuffer(layer, firstBuffer, releaseCallback->getCallback());
+ t.setBuffer(layer, firstBuffer, firstBufferCallbackId, releaseCallback->getCallback());
t.setAcquireFence(layer, Fence::NO_FENCE);
t.addTransactionCompletedCallback(transactionCallback.function,
transactionCallback.getContext());
@@ -295,7 +317,8 @@
// Dropping frames in transaction queue emits a callback
sp<GraphicBuffer> secondBuffer = getBuffer();
- t.setBuffer(layer, secondBuffer, releaseCallback->getCallback());
+ ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+ t.setBuffer(layer, secondBuffer, secondBufferCallbackId, releaseCallback->getCallback());
t.setAcquireFence(layer, Fence::NO_FENCE);
t.addTransactionCompletedCallback(transactionCallback.function,
transactionCallback.getContext());
@@ -307,7 +330,7 @@
ExpectedResult::Buffer::NOT_ACQUIRED,
ExpectedResult::PreviousBuffer::RELEASED);
ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
- ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
}
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 0a8c748..97b60e0 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -160,7 +160,7 @@
size_t maxTokens;
static constexpr pid_t kSurfaceFlingerPid = 666;
static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
- static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(0ns).count();
static constexpr nsecs_t kStartThreshold = std::chrono::nanoseconds(2ns).count();
static constexpr JankClassificationThresholds kTestThresholds{kPresentThreshold,
kDeadlineThreshold,
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 9bb5ca1..3423bd5 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -2066,6 +2066,35 @@
EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
}
+TEST_F(RefreshRateConfigsTest, testKernelIdleTimerActionFor120Hz) {
+ using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
+
+ // Tests with 120Hz
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_120);
+ // SetPolicy(0, 60), current 60Hz => TurnOn.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(0), Fps(60)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());
+
+ // SetPolicy(60, 60), current 60Hz => TurnOff.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
+
+ // SetPolicy(60, 120), current 60Hz => TurnOn.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(120)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());
+
+ // SetPolicy(120, 120), current 120Hz => TurnOff.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_120, {Fps(120), Fps(120)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
+}
+
TEST_F(RefreshRateConfigsTest, getFrameRateDivider) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index 7450b5d..159bdf1 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -27,8 +27,10 @@
PowerAdvisor();
~PowerAdvisor() override;
+ MOCK_METHOD0(init, void());
MOCK_METHOD0(onBootFinished, void());
MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+ MOCK_METHOD0(isUsingExpensiveRendering, bool());
MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};