Merge "[SF] Adds callback from the VsyncPredictor" into main
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c40caf5..c86adef 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -353,7 +353,7 @@
// Now go on and read dexopt lines from stdin and pass them on to otapreopt.
int count = 1;
- for (std::array<char, 1000> linebuf;
+ for (std::array<char, 10000> linebuf;
std::cin.clear(), std::cin.getline(&linebuf[0], linebuf.size()); ++count) {
// Subtract one from gcount() since getline() counts the newline.
std::string line(&linebuf[0], std::cin.gcount() - 1);
diff --git a/data/etc/android.software.opengles.deqp.level-latest.xml b/data/etc/android.software.opengles.deqp.level-latest.xml
index bd15eb6..62bb101 100644
--- a/data/etc/android.software.opengles.deqp.level-latest.xml
+++ b/data/etc/android.software.opengles.deqp.level-latest.xml
@@ -17,5 +17,5 @@
<!-- This is the standard feature indicating that the device passes OpenGL ES
dEQP tests associated with the most recent level for this Android version. -->
<permissions>
- <feature name="android.software.opengles.deqp.level" version="132580097" />
+ <feature name="android.software.opengles.deqp.level" version="132645633" />
</permissions>
diff --git a/data/etc/android.software.vulkan.deqp.level-latest.xml b/data/etc/android.software.vulkan.deqp.level-latest.xml
index 87be070..0fc12b3 100644
--- a/data/etc/android.software.vulkan.deqp.level-latest.xml
+++ b/data/etc/android.software.vulkan.deqp.level-latest.xml
@@ -17,5 +17,5 @@
<!-- This is the standard feature indicating that the device passes Vulkan
dEQP tests associated with the most recent level for this Android version. -->
<permissions>
- <feature name="android.software.vulkan.deqp.level" version="132580097" />
+ <feature name="android.software.vulkan.deqp.level" version="132645633" />
</permissions>
diff --git a/include/input/VelocityTracker.h b/include/input/VelocityTracker.h
index 2e99495..ee74455 100644
--- a/include/input/VelocityTracker.h
+++ b/include/input/VelocityTracker.h
@@ -98,7 +98,7 @@
void addMovement(nsecs_t eventTime, int32_t pointerId, int32_t axis, float position);
// Adds movement information for all pointers in a MotionEvent, including historical samples.
- void addMovement(const MotionEvent* event);
+ void addMovement(const MotionEvent& event);
// Returns the velocity of the specified pointer id and axis in position units per second.
// Returns empty optional if there is insufficient movement information for the pointer, or if
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index f22e90a..8243238 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -30,7 +30,6 @@
#include <binder/RecordedTransaction.h>
#include <binder/RpcServer.h>
#include <pthread.h>
-#include <utils/misc.h>
#include <inttypes.h>
#include <stdio.h>
@@ -271,7 +270,7 @@
bool mInheritRt = false;
// for below objects
- Mutex mLock;
+ RpcMutex mLock;
std::set<sp<RpcServerLink>> mRpcServerLinks;
BpBinder::ObjectManager mObjects;
@@ -307,7 +306,7 @@
return PERMISSION_DENIED;
}
Extras* e = getOrCreateExtras();
- AutoMutex lock(e->mLock);
+ RpcMutexUniqueLock lock(e->mLock);
if (mRecordingOn) {
LOG(INFO) << "Could not start Binder recording. Another is already in progress.";
return INVALID_OPERATION;
@@ -337,7 +336,7 @@
return PERMISSION_DENIED;
}
Extras* e = getOrCreateExtras();
- AutoMutex lock(e->mLock);
+ RpcMutexUniqueLock lock(e->mLock);
if (mRecordingOn) {
e->mRecordingFd.reset();
mRecordingOn = false;
@@ -405,7 +404,7 @@
if (kEnableKernelIpc && mRecordingOn && code != START_RECORDING_TRANSACTION) [[unlikely]] {
Extras* e = mExtras.load(std::memory_order_acquire);
- AutoMutex lock(e->mLock);
+ RpcMutexUniqueLock lock(e->mLock);
if (mRecordingOn) {
Parcel emptyReply;
timespec ts;
@@ -452,7 +451,7 @@
Extras* e = getOrCreateExtras();
LOG_ALWAYS_FATAL_IF(!e, "no memory");
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
return e->mObjects.attach(objectID, object, cleanupCookie, func);
}
@@ -461,7 +460,7 @@
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) return nullptr;
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
return e->mObjects.find(objectID);
}
@@ -469,7 +468,7 @@
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) return nullptr;
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
return e->mObjects.detach(objectID);
}
@@ -477,7 +476,7 @@
Extras* e = getOrCreateExtras();
LOG_ALWAYS_FATAL_IF(!e, "no memory");
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
doWithLock();
}
@@ -485,7 +484,7 @@
const void* makeArgs) {
Extras* e = getOrCreateExtras();
LOG_ALWAYS_FATAL_IF(!e, "no memory");
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
}
@@ -692,7 +691,7 @@
auto weakThis = wp<BBinder>::fromExisting(this);
Extras* e = getOrCreateExtras();
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
auto rpcServer = RpcServer::make();
LOG_ALWAYS_FATAL_IF(rpcServer == nullptr, "RpcServer::make returns null");
auto link = sp<RpcServerLink>::make(rpcServer, keepAliveBinder, weakThis);
@@ -716,7 +715,7 @@
void BBinder::removeRpcServerLink(const sp<RpcServerLink>& link) {
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) return;
- AutoMutex _l(e->mLock);
+ RpcMutexUniqueLock _l(e->mLock);
(void)e->mRpcServerLinks.erase(link);
}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 3bc4f92..49038b1 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -23,7 +23,6 @@
#include <binder/IResultReceiver.h>
#include <binder/RpcSession.h>
#include <binder/Stability.h>
-#include <utils/Log.h>
#include <stdio.h>
@@ -38,7 +37,7 @@
// ---------------------------------------------------------------------------
-Mutex BpBinder::sTrackingLock;
+RpcMutex BpBinder::sTrackingLock;
std::unordered_map<int32_t, uint32_t> BpBinder::sTrackingMap;
std::unordered_map<int32_t, uint32_t> BpBinder::sLastLimitCallbackMap;
int BpBinder::sNumTrackedUids = 0;
@@ -163,7 +162,7 @@
int32_t trackedUid = -1;
if (sCountByUidEnabled) {
trackedUid = IPCThreadState::self()->getCallingUid();
- AutoMutex _l(sTrackingLock);
+ RpcMutexUniqueLock _l(sTrackingLock);
uint32_t trackedValue = sTrackingMap[trackedUid];
if (trackedValue & LIMIT_REACHED_MASK) [[unlikely]] {
if (sBinderProxyThrottleCreate) {
@@ -276,7 +275,7 @@
}
bool BpBinder::isDescriptorCached() const {
- Mutex::Autolock _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
return mDescriptorCache.c_str() != kDescriptorUninit.c_str();
}
@@ -292,7 +291,7 @@
status_t err = thiz->transact(INTERFACE_TRANSACTION, data, &reply);
if (err == NO_ERROR) {
String16 res(reply.readString16());
- Mutex::Autolock _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
// mDescriptorCache could have been assigned while the lock was
// released.
if (mDescriptorCache.c_str() == kDescriptorUninit.c_str()) mDescriptorCache = res;
@@ -385,7 +384,7 @@
status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
}
if (data.dataSize() > LOG_TRANSACTIONS_OVER_SIZE) {
- Mutex::Autolock _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d",
data.dataSize(), String8(mDescriptorCache).c_str(), code);
}
@@ -431,7 +430,7 @@
"linkToDeath(): recipient must be non-NULL");
{
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
if (!mObitsSent) {
if (!mObituaries) {
@@ -467,7 +466,7 @@
return INVALID_OPERATION;
}
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
if (mObitsSent) {
return DEAD_OBJECT;
@@ -555,30 +554,30 @@
void* BpBinder::attachObject(const void* objectID, void* object, void* cleanupCookie,
object_cleanup_func func) {
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
return mObjects.attach(objectID, object, cleanupCookie, func);
}
void* BpBinder::findObject(const void* objectID) const
{
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
return mObjects.find(objectID);
}
void* BpBinder::detachObject(const void* objectID) {
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
return mObjects.detach(objectID);
}
void BpBinder::withLock(const std::function<void()>& doWithLock) {
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
doWithLock();
}
sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
const void* makeArgs) {
- AutoMutex _l(mLock);
+ RpcMutexUniqueLock _l(mLock);
return mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
}
@@ -602,7 +601,7 @@
IPCThreadState* ipc = IPCThreadState::self();
if (mTrackedUid >= 0) {
- AutoMutex _l(sTrackingLock);
+ RpcMutexUniqueLock _l(sTrackingLock);
uint32_t trackedValue = sTrackingMap[mTrackedUid];
if ((trackedValue & COUNTING_VALUE_MASK) == 0) [[unlikely]] {
ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this,
@@ -702,7 +701,7 @@
uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
{
- AutoMutex _l(sTrackingLock);
+ RpcMutexUniqueLock _l(sTrackingLock);
auto it = sTrackingMap.find(uid);
if (it != sTrackingMap.end()) {
return it->second & COUNTING_VALUE_MASK;
@@ -717,7 +716,7 @@
void BpBinder::getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts)
{
- AutoMutex _l(sTrackingLock);
+ RpcMutexUniqueLock _l(sTrackingLock);
uids.setCapacity(sTrackingMap.size());
counts.setCapacity(sTrackingMap.size());
for (const auto& it : sTrackingMap) {
@@ -731,12 +730,12 @@
void BpBinder::setCountByUidEnabled(bool enable) { sCountByUidEnabled.store(enable); }
void BpBinder::setLimitCallback(binder_proxy_limit_callback cb) {
- AutoMutex _l(sTrackingLock);
+ RpcMutexUniqueLock _l(sTrackingLock);
sLimitCallback = cb;
}
void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
- AutoMutex _l(sTrackingLock);
+ RpcMutexUniqueLock _l(sTrackingLock);
sBinderProxyCountHighWatermark = high;
sBinderProxyCountLowWatermark = low;
}
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index c6e4fb3..7ae616e 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -19,8 +19,6 @@
#include <binder/ProcessState.h>
-#include <utils/misc.h>
-
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index 2780bd4..dea2603 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -15,7 +15,6 @@
*/
#define LOG_TAG "IInterface"
-#include <utils/Log.h>
#include <binder/IInterface.h>
namespace android {
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
index cd92217..60ece72 100644
--- a/libs/binder/IResultReceiver.cpp
+++ b/libs/binder/IResultReceiver.cpp
@@ -18,7 +18,6 @@
#include <binder/IResultReceiver.h>
-#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 6034f2b..fe566fc 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -200,7 +200,7 @@
}
bool checkPermission(const String16& permission, pid_t pid, uid_t uid, bool logPermissionFailure) {
- static Mutex gPermissionControllerLock;
+ static std::mutex gPermissionControllerLock;
static sp<IPermissionController> gPermissionController;
sp<IPermissionController> pc;
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index 5b1cb7e..95bdbb4 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -155,7 +155,7 @@
void dump_l(String8& res, const char* what) const;
static const int kMemoryAlign;
- mutable Mutex mLock;
+ mutable std::mutex mLock;
LinkedList<chunk_t> mList;
size_t mHeapSize;
};
@@ -305,14 +305,14 @@
size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
{
- Mutex::Autolock _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
ssize_t offset = alloc(size, flags);
return offset;
}
status_t SimpleBestFitAllocator::deallocate(size_t offset)
{
- Mutex::Autolock _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
chunk_t const * const freed = dealloc(offset);
if (freed) {
return NO_ERROR;
@@ -420,7 +420,7 @@
void SimpleBestFitAllocator::dump(const char* what) const
{
- Mutex::Autolock _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
dump_l(what);
}
@@ -434,7 +434,7 @@
void SimpleBestFitAllocator::dump(String8& result,
const char* what) const
{
- Mutex::Autolock _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
dump_l(result, what);
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a3ff7d2..6d2e12b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "Parcel"
//#define LOG_NDEBUG 0
+#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -43,11 +44,8 @@
#ifndef BINDER_DISABLE_BLOB
#include <cutils/ashmem.h>
#endif
-#include <utils/Flattenable.h>
-#include <utils/Log.h>
#include <utils/String16.h>
#include <utils/String8.h>
-#include <utils/misc.h>
#include "OS.h"
#include "RpcState.h"
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 8ec4af9..58203c1 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -189,7 +189,7 @@
void ProcessState::startThreadPool()
{
- AutoMutex _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
if (!mThreadPoolStarted) {
if (mMaxThreads == 0) {
// see also getThreadPoolMaxTotalThreadCount
@@ -203,7 +203,7 @@
bool ProcessState::becomeContextManager()
{
- AutoMutex _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
flat_binder_object obj {
.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
@@ -310,7 +310,7 @@
{
sp<IBinder> result;
- AutoMutex _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
if (handle == 0 && the_context_object != nullptr) return the_context_object;
@@ -374,7 +374,7 @@
void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
{
- AutoMutex _l(mLock);
+ std::unique_lock<std::mutex> _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 07ab093..1011571 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -30,7 +30,6 @@
#include <binder/RpcServer.h>
#include <binder/RpcTransportRaw.h>
#include <log/log.h>
-#include <utils/Compat.h>
#include "BuildFlags.h"
#include "FdTrigger.h"
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index fa8f2b5..c8aff63 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -33,7 +33,6 @@
#include <binder/RpcServer.h>
#include <binder/RpcTransportRaw.h>
#include <binder/Stability.h>
-#include <utils/Compat.h>
#include <utils/String8.h>
#include "BuildFlags.h"
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 26a2f4f..749c2f8 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -412,10 +412,8 @@
return false;
}
#else
- // TODO(b/305983144)
- // don't restrict on other platforms, though experimental should
- // only really be used for testing, we don't have a good way to see
- // what is shipping outside of Android
+ ALOGE("Cannot use experimental RPC binder protocol outside of Android.");
+ return false;
#endif
} else if (version >= RPC_WIRE_PROTOCOL_VERSION_NEXT) {
ALOGE("Cannot use RPC binder protocol version %u which is unknown (current protocol "
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index dd632c0..8942c31 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -22,6 +22,19 @@
#include <log/log.h>
#include <utils/Errors.h>
+/* TEMP_FAILURE_RETRY is not available on macOS and Trusty. */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ __typeof__(exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; \
+ })
+#endif
+
#define TEST_AND_RETURN(value, expr) \
do { \
if (!(expr)) { \
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 28fb9f1..d78ea0d 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -18,7 +18,7 @@
#include <android-base/unique_fd.h>
#include <binder/IBinder.h>
-#include <utils/Mutex.h>
+#include <binder/RpcThreads.h>
#include <map>
#include <optional>
@@ -193,7 +193,7 @@
void reportOneDeath(const Obituary& obit);
bool isDescriptorCached() const;
- mutable Mutex mLock;
+ mutable RpcMutex mLock;
volatile int32_t mAlive;
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
@@ -201,7 +201,7 @@
mutable String16 mDescriptorCache;
int32_t mTrackedUid;
- static Mutex sTrackingLock;
+ static RpcMutex sTrackingLock;
static std::unordered_map<int32_t,uint32_t> sTrackingMap;
static int sNumTrackedUids;
static std::atomic_bool sCountByUidEnabled;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 98d12bb..6961abc 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -33,7 +33,6 @@
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <utils/Vector.h>
-#include <utils/Flattenable.h>
#include <binder/IInterface.h>
#include <binder/Parcelable.h>
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 9dc370b..3672702 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -17,13 +17,13 @@
#pragma once
#include <binder/IBinder.h>
-#include <utils/KeyedVector.h>
-#include <utils/Mutex.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <pthread.h>
+#include <mutex>
+
// ---------------------------------------------------------------------------
namespace android {
@@ -178,7 +178,7 @@
// Time when thread pool was emptied
int64_t mStarvationStartTimeMs;
- mutable Mutex mLock; // protects everything below.
+ mutable std::mutex mLock; // protects everything below.
Vector<handle_entry> mHandleToObject;
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 341e9ce..659943a 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -40,6 +40,7 @@
#include <binder/IServiceManager.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
+#include <utils/Flattenable.h>
#include <linux/sched.h>
#include <sys/epoll.h>
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index 786fab8..c3070dd 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -74,8 +74,7 @@
#ifdef __ANDROID__
return base::GetProperty("ro.build.version.codename", "") != "REL";
#else
- // TODO(b/305983144): restrict on other platforms
- return true;
+ return false;
#endif
}
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 1c13866..cbbbe74 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -28,6 +28,7 @@
#include <gtest/gtest.h>
#pragma clang diagnostic pop
+#include <utils/Flattenable.h>
#include <utils/LightRefBase.h>
#include <utils/NativeHandle.h>
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index 383795e..fe79f8e 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -32,7 +32,11 @@
host_supported: true,
fuzz_config: {
- cc: ["smoreland@google.com"],
+ cc: [
+ "smoreland@google.com",
+ "waghpawan@google.com",
+ ],
+ use_for_presubmit: true,
},
srcs: [
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 416ffad..ffeca2d 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -25,6 +25,7 @@
#include <binder/ParcelableHolder.h>
#include <binder/PersistableBundle.h>
#include <binder/Status.h>
+#include <utils/Flattenable.h>
#include "../../Utils.h"
diff --git a/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp b/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp
index e494366..f3006cd 100644
--- a/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp
+++ b/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp
@@ -35,7 +35,7 @@
if (transaction.has_value()) {
intermediateFile = std::tmpfile();
- android::base::unique_fd fdForWriting(fileno(intermediateFile));
+ android::base::unique_fd fdForWriting(dup(fileno(intermediateFile)));
auto writeStatus ATTRIBUTE_UNUSED = transaction.value().dumpToFile(fdForWriting);
std::fclose(intermediateFile);
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index d4605ea..3fe71ce 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -34,5 +34,7 @@
"libbase",
"liblog",
],
+ static_libs: ["libguiflags"],
export_include_dirs: ["include"],
+ export_static_lib_headers: ["libguiflags"],
}
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index ed5d5c1..394a000 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -575,17 +575,23 @@
return mAngleNamespace;
}
- if (mAnglePath.empty() && !mShouldUseSystemAngle) {
- ALOGV("mAnglePath is empty and not using system ANGLE, abort creating ANGLE namespace");
+ // If ANGLE path is not set, it means ANGLE should not be used for this process;
+ // or if ANGLE path is set and set to use system ANGLE, then a namespace is not needed
+ // because:
+ // 1) if the default OpenGL ES driver is already ANGLE, then the loader will skip;
+ // 2) if the default OpenGL ES driver is native, then there's no symbol conflict;
+ // 3) if there's no OpenGL ES driver is preloaded, then there's no symbol conflict.
+ if (mAnglePath.empty() || mShouldUseSystemAngle) {
+ ALOGV("mAnglePath is empty or use system ANGLE, abort creating ANGLE namespace");
return nullptr;
}
// Construct the search paths for system ANGLE.
const char* const defaultLibraryPaths =
#if defined(__LP64__)
- "/vendor/lib64/egl:/system/lib64/egl";
+ "/vendor/lib64/egl:/system/lib64";
#else
- "/vendor/lib/egl:/system/lib/egl";
+ "/vendor/lib/egl:/system/lib";
#endif
// If the application process will run on top of system ANGLE, construct the namespace
diff --git a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
index 47607a0..9ebaf16 100644
--- a/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
+++ b/libs/graphicsenv/include/graphicsenv/GpuStatsInfo.h
@@ -104,7 +104,7 @@
GL_UPDATED = 2,
VULKAN = 3,
VULKAN_UPDATED = 4,
- ANGLE = 5,
+ ANGLE = 5, // cover both system ANGLE and ANGLE APK
};
enum Stats {
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index f17a654..c84ee1f 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -20,6 +20,25 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+aconfig_declarations {
+ name: "libgui_flags",
+ package: "com.android.graphics.libgui.flags",
+ srcs: ["libgui_flags.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "libguiflags",
+ host_supported: true,
+ vendor_available: true,
+ min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
+ aconfig_declarations: "libgui_flags",
+}
+
cc_library_headers {
name: "libgui_headers",
vendor_available: true,
@@ -36,6 +55,8 @@
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
],
+ static_libs: ["libguiflags"],
+ export_static_lib_headers: ["libguiflags"],
min_sdk_version: "29",
// TODO(b/218719284) can media use be constrained to libgui_bufferqueue_static?
apex_available: [
@@ -192,19 +213,6 @@
},
}
-aconfig_declarations {
- name: "libgui_flags",
- package: "com.android.graphics.libgui.flags",
- srcs: ["libgui_flags.aconfig"],
-}
-
-cc_aconfig_library {
- name: "libguiflags",
- host_supported: true,
- vendor_available: true,
- aconfig_declarations: "libgui_flags",
-}
-
filegroup {
name: "libgui-sources",
srcs: [
@@ -265,6 +273,9 @@
"libbinder",
"libGLESv2",
],
+ export_static_lib_headers: [
+ "libguiflags",
+ ],
}
cc_library_shared {
@@ -460,6 +471,7 @@
static_libs: [
"libgtest",
"libgmock",
+ "libguiflags",
],
srcs: [
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index dd0a028..8d0331e 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -26,7 +26,7 @@
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
-#include <gui/Flags.h>
+
#include <gui/FrameRateUtils.h>
#include <gui/GLConsumer.h>
#include <gui/IProducerListener.h>
@@ -41,8 +41,6 @@
#include <android-base/thread_annotations.h>
#include <chrono>
-#include <com_android_graphics_libgui_flags.h>
-
using namespace com::android::graphics::libgui;
using namespace std::chrono_literals;
@@ -144,7 +142,7 @@
}
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
void BLASTBufferItemConsumer::onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index ab0f6d2..b0f6e69 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -22,7 +22,6 @@
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
-#include <gui/Flags.h>
namespace android {
@@ -99,7 +98,7 @@
}
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
void BufferQueue::ProxyConsumerListener::onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
sp<ConsumerListener> listener(mConsumerListener.promote());
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 67dff6d..19693e3 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -32,7 +32,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
-#include <gui/Flags.h>
+
#include <gui/FrameRateUtils.h>
#include <gui/GLConsumer.h>
#include <gui/IConsumerListener.h>
@@ -1753,7 +1753,7 @@
return NO_ERROR;
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
status_t BufferQueueProducer::setFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
ATRACE_CALL();
diff --git a/libs/gui/FrameRateUtils.cpp b/libs/gui/FrameRateUtils.cpp
index 6993bfa..11524e2 100644
--- a/libs/gui/FrameRateUtils.cpp
+++ b/libs/gui/FrameRateUtils.cpp
@@ -14,14 +14,16 @@
* limitations under the License.
*/
-#include <gui/Flags.h>
#include <gui/FrameRateUtils.h>
#include <system/window.h>
#include <utils/Log.h>
#include <cmath>
+#include <com_android_graphics_libgui_flags.h>
+
namespace android {
+using namespace com::android::graphics::libgui;
// Returns true if the frameRate is valid.
//
// @param frameRate the frame rate in Hz
@@ -53,7 +55,7 @@
changeFrameRateStrategy != ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS) {
ALOGE("%s failed - invalid change frame rate strategy value %d", functionName,
changeFrameRateStrategy);
- if (FLAG_BQ_SET_FRAME_RATE) {
+ if (flags::bq_setframerate()) {
return false;
}
}
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index d0c09e4..e81c098 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -28,7 +28,7 @@
#include <binder/IInterface.h>
#include <gui/BufferQueueDefs.h>
-#include <gui/Flags.h>
+
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
@@ -763,7 +763,7 @@
}
return result;
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
virtual status_t setFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) override {
Parcel data, reply;
@@ -973,7 +973,7 @@
return INVALID_OPERATION;
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
status_t IGraphicBufferProducer::setFrameRate(float /*frameRate*/, int8_t /*compatibility*/,
int8_t /*changeFrameRateStrategy*/) {
// No-op for IGBP other than BufferQueue.
@@ -1522,7 +1522,7 @@
reply->writeInt32(result);
return NO_ERROR;
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
case SET_FRAME_RATE: {
CHECK_INTERFACE(IGraphicBuffer, data, reply);
float frameRate = data.readFloat();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a87f053..07a0cfe 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -43,7 +43,7 @@
#include <gui/AidlStatusUtil.h>
#include <gui/BufferItem.h>
-#include <gui/Flags.h>
+
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
@@ -2571,7 +2571,7 @@
status_t Surface::setFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
if (flags::bq_setframerate()) {
status_t err = mGraphicBufferProducer->setFrameRate(frameRate, compatibility,
changeFrameRateStrategy);
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 02d7c4d..892215e 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -19,7 +19,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
-#include <gui/Flags.h>
+
#include <gui/IGraphicBufferProducer.h>
#include <gui/SurfaceComposerClient.h>
@@ -31,6 +31,8 @@
#include <thread>
#include <queue>
+#include <com_android_graphics_libgui_flags.h>
+
namespace android {
class BLASTBufferQueue;
@@ -59,7 +61,7 @@
protected:
void onSidebandStreamChanged() override EXCLUDES(mMutex);
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
void onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) override;
#endif
diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
index 2756277..0948c4d0 100644
--- a/libs/gui/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -19,11 +19,13 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueueDefs.h>
-#include <gui/Flags.h>
+
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
+#include <com_android_graphics_libgui_flags.h>
+
namespace android {
class BufferQueue {
@@ -70,7 +72,7 @@
void addAndGetFrameTimestamps(
const NewFrameEventsEntry* newTimestamps,
FrameEventHistoryDelta* outDelta) override;
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
void onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) override;
#endif
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 38805d0..de47483 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -18,7 +18,7 @@
#define ANDROID_GUI_BUFFERQUEUEPRODUCER_H
#include <gui/BufferQueueDefs.h>
-#include <gui/Flags.h>
+
#include <gui/IGraphicBufferProducer.h>
namespace android {
@@ -202,7 +202,7 @@
// See IGraphicBufferProducer::setAutoPrerotation
virtual status_t setAutoPrerotation(bool autoPrerotation);
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
// See IGraphicBufferProducer::setFrameRate
status_t setFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) override;
diff --git a/libs/gui/include/gui/Flags.h b/libs/gui/include/gui/Flags.h
deleted file mode 100644
index a2cff56..0000000
--- a/libs/gui/include/gui/Flags.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-// TODO(281695725): replace this with build time flags, whenever they are available
-#ifndef FLAG_BQ_SET_FRAME_RATE
-#define FLAG_BQ_SET_FRAME_RATE false
-#endif
\ No newline at end of file
diff --git a/libs/gui/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h
index e183bf2..51d3959 100644
--- a/libs/gui/include/gui/IConsumerListener.h
+++ b/libs/gui/include/gui/IConsumerListener.h
@@ -19,13 +19,13 @@
#include <binder/IInterface.h>
#include <binder/SafeInterface.h>
-#include <gui/Flags.h>
-
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <cstdint>
+#include <com_android_graphics_libgui_flags.h>
+
namespace android {
class BufferItem;
@@ -93,7 +93,7 @@
virtual void addAndGetFrameTimestamps(const NewFrameEventsEntry* /*newTimestamps*/,
FrameEventHistoryDelta* /*outDelta*/) {}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
// Notifies the consumer of a setFrameRate call from the producer side.
virtual void onSetFrameRate(float /*frameRate*/, int8_t /*compatibility*/,
int8_t /*changeFrameRateStrategy*/) {}
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 3562906..7639e70 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -31,7 +31,6 @@
#include <ui/Rect.h>
#include <ui/Region.h>
-#include <gui/Flags.h>
#include <gui/FrameTimestamps.h>
#include <gui/HdrMetadata.h>
@@ -42,6 +41,8 @@
#include <optional>
#include <vector>
+#include <com_android_graphics_libgui_flags.h>
+
namespace android {
// ----------------------------------------------------------------------------
@@ -677,7 +678,7 @@
// the width and height used for dequeueBuffer will be additionally swapped.
virtual status_t setAutoPrerotation(bool autoPrerotation);
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
// Sets the apps intended frame rate.
virtual status_t setFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy);
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 38c0eed..6dcd501 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -21,7 +21,7 @@
"-Wall",
"-Werror",
"-Wno-extra",
- "-DFLAG_BQ_SET_FRAME_RATE=true",
+ "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_SETFRAMERATE=true",
],
srcs: [
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 17aa5f1..1410c7d 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -1266,9 +1266,7 @@
}
TEST_F(BufferQueueTest, TestBqSetFrameRateFlagBuildTimeIsSet) {
- if (flags::bq_setframerate()) {
- ASSERT_EQ(true, FLAG_BQ_SET_FRAME_RATE);
- }
+ ASSERT_EQ(flags::bq_setframerate(), COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE));
}
struct BufferItemConsumerSetFrameRateListener : public BufferItemConsumer {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index e7b1232..86ced2c 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -1341,7 +1341,7 @@
newFrame->mRefreshes[0].mGpuCompositionDone.mFenceTime :
FenceTime::NO_FENCE;
// HWC2 releases the previous buffer after a new latch just before
- // calling postComposition.
+ // calling onCompositionPresented.
if (oldFrame != nullptr) {
mCfeh->addRelease(nOldFrame, oldFrame->kDequeueReadyTime,
std::shared_ptr<FenceTime>(oldFrame->mRelease.mFenceTime));
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 116b778..613a0df 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -275,10 +275,10 @@
}
}
-void VelocityTracker::addMovement(const MotionEvent* event) {
+void VelocityTracker::addMovement(const MotionEvent& event) {
// Stores data about which axes to process based on the incoming motion event.
std::set<int32_t> axesToProcess;
- int32_t actionMasked = event->getActionMasked();
+ int32_t actionMasked = event.getActionMasked();
switch (actionMasked) {
case AMOTION_EVENT_ACTION_DOWN:
@@ -291,7 +291,7 @@
// Start a new movement trace for a pointer that just went down.
// We do this on down instead of on up because the client may want to query the
// final velocity for a pointer that just went up.
- clearPointer(event->getPointerId(event->getActionIndex()));
+ clearPointer(event.getPointerId(event.getActionIndex()));
axesToProcess.insert(PLANAR_AXES.begin(), PLANAR_AXES.end());
break;
}
@@ -300,8 +300,14 @@
axesToProcess.insert(PLANAR_AXES.begin(), PLANAR_AXES.end());
break;
case AMOTION_EVENT_ACTION_POINTER_UP:
+ if (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) {
+ clearPointer(event.getPointerId(event.getActionIndex()));
+ return;
+ }
+ // Continue to ACTION_UP to ensure that the POINTER_STOPPED logic is triggered.
+ [[fallthrough]];
case AMOTION_EVENT_ACTION_UP: {
- std::chrono::nanoseconds delaySinceLastEvent(event->getEventTime() - mLastEventTime);
+ std::chrono::nanoseconds delaySinceLastEvent(event.getEventTime() - mLastEventTime);
if (delaySinceLastEvent > ASSUME_POINTER_STOPPED_TIME) {
ALOGD_IF(DEBUG_VELOCITY,
"VelocityTracker: stopped for %s, clearing state upon pointer liftoff.",
@@ -325,21 +331,26 @@
case AMOTION_EVENT_ACTION_SCROLL:
axesToProcess.insert(AMOTION_EVENT_AXIS_SCROLL);
break;
+ case AMOTION_EVENT_ACTION_CANCEL: {
+ clear();
+ return;
+ }
+
default:
// Ignore all other actions.
return;
}
- const size_t historySize = event->getHistorySize();
+ const size_t historySize = event.getHistorySize();
for (size_t h = 0; h <= historySize; h++) {
- const nsecs_t eventTime = event->getHistoricalEventTime(h);
- for (size_t i = 0; i < event->getPointerCount(); i++) {
- if (event->isResampled(i, h)) {
+ const nsecs_t eventTime = event.getHistoricalEventTime(h);
+ for (size_t i = 0; i < event.getPointerCount(); i++) {
+ if (event.isResampled(i, h)) {
continue; // skip resampled samples
}
- const int32_t pointerId = event->getPointerId(i);
+ const int32_t pointerId = event.getPointerId(i);
for (int32_t axis : axesToProcess) {
- const float position = event->getHistoricalAxisValue(axis, i, h);
+ const float position = event.getHistoricalAxisValue(axis, i, h);
addMovement(eventTime, pointerId, axis, position);
}
}
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 978a80f..3672387 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -48,3 +48,17 @@
description: "Enable additional palm rejection on touchpad while typing"
bug: "301055381"
}
+
+flag {
+ name: "remove_app_switch_drops"
+ namespace: "input"
+ description: "Remove the logic of dropping events due to pending app switch"
+ bug: "284808102"
+}
+
+flag {
+ name: "disable_reject_touch_on_stylus_hover"
+ namespace: "input"
+ description: "Disable touch rejection when the stylus hovers the screen"
+ bug: "301216095"
+}
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index bbc6d98..5f05a0f 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -118,18 +118,17 @@
match action.into() {
MotionAction::Down => {
+ if self.touching_pointer_ids_by_device.contains_key(&device_id) {
+ return Err(format!(
+ "{}: Invalid DOWN event - pointers already down for device {:?}: {:?}",
+ self.name, device_id, self.touching_pointer_ids_by_device
+ ));
+ }
let it = self
.touching_pointer_ids_by_device
.entry(device_id)
.or_insert_with(HashSet::new);
- let pointer_id = pointer_properties[0].id;
- if it.contains(&pointer_id) {
- return Err(format!(
- "{}: Invalid DOWN event - pointers already down for device {:?}: {:?}",
- self.name, device_id, it
- ));
- }
- it.insert(pointer_id);
+ it.insert(pointer_properties[0].id);
}
MotionAction::PointerDown { action_index } => {
if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
@@ -353,6 +352,56 @@
}
#[test]
+ fn two_pointer_stream() {
+ let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ Source::Touchscreen,
+ input_bindgen::AMOTION_EVENT_ACTION_DOWN,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+ // POINTER 1 DOWN
+ let two_pointer_properties =
+ Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ Source::Touchscreen,
+ input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN
+ | (1 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ &two_pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+ // POINTER 0 UP
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ Source::Touchscreen,
+ input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP
+ | (0 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ &two_pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+ // ACTION_UP for pointer id=1
+ let pointer_1_properties = Vec::from([RustPointerProperties { id: 1 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ Source::Touchscreen,
+ input_bindgen::AMOTION_EVENT_ACTION_UP,
+ &pointer_1_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+ }
+
+ #[test]
fn multi_device_stream() {
let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 1c8ec90..f9ca280 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -229,41 +229,23 @@
return events;
}
-static std::optional<float> computePlanarVelocity(
- const VelocityTracker::Strategy strategy,
- const std::vector<PlanarMotionEventEntry>& motions, int32_t axis,
- uint32_t pointerId = DEFAULT_POINTER_ID) {
+static std::optional<float> computeVelocity(const VelocityTracker::Strategy strategy,
+ const std::vector<MotionEvent>& events, int32_t axis,
+ uint32_t pointerId = DEFAULT_POINTER_ID) {
VelocityTracker vt(strategy);
- std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
- for (MotionEvent event : events) {
- vt.addMovement(&event);
+ for (const MotionEvent& event : events) {
+ vt.addMovement(event);
}
return vt.getVelocity(axis, pointerId);
}
-static std::vector<MotionEvent> createMotionEventStream(
- int32_t axis, const std::vector<std::pair<std::chrono::nanoseconds, float>>& motion) {
- switch (axis) {
- case AMOTION_EVENT_AXIS_SCROLL:
- return createAxisScrollMotionEventStream(motion);
- default:
- ADD_FAILURE() << "Axis " << axis << " is not supported";
- return {};
- }
-}
-
-static std::optional<float> computeVelocity(
+static std::optional<float> computePlanarVelocity(
const VelocityTracker::Strategy strategy,
- const std::vector<std::pair<std::chrono::nanoseconds, float>>& motions, int32_t axis) {
- VelocityTracker vt(strategy);
-
- for (const MotionEvent& event : createMotionEventStream(axis, motions)) {
- vt.addMovement(&event);
- }
-
- return vt.getVelocity(axis, DEFAULT_POINTER_ID);
+ const std::vector<PlanarMotionEventEntry>& motions, int32_t axis, uint32_t pointerId) {
+ std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
+ return computeVelocity(strategy, events, axis, pointerId);
}
static void computeAndCheckVelocity(const VelocityTracker::Strategy strategy,
@@ -277,23 +259,23 @@
const VelocityTracker::Strategy strategy,
const std::vector<std::pair<std::chrono::nanoseconds, float>>& motions,
std::optional<float> targetVelocity) {
- checkVelocity(computeVelocity(strategy, motions, AMOTION_EVENT_AXIS_SCROLL), targetVelocity);
+ std::vector<MotionEvent> events = createAxisScrollMotionEventStream(motions);
+ checkVelocity(computeVelocity(strategy, events, AMOTION_EVENT_AXIS_SCROLL), targetVelocity);
// The strategy LSQ2 is not compatible with AXIS_SCROLL. In those situations, we should fall
// back to a strategy that supports differential axes.
- checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, motions,
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events,
AMOTION_EVENT_AXIS_SCROLL),
targetVelocity);
}
static void computeAndCheckQuadraticVelocity(const std::vector<PlanarMotionEventEntry>& motions,
float velocity) {
- VelocityTracker vt(VelocityTracker::Strategy::LSQ2);
- std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
- for (MotionEvent event : events) {
- vt.addMovement(&event);
- }
- std::optional<float> velocityX = vt.getVelocity(AMOTION_EVENT_AXIS_X, 0);
- std::optional<float> velocityY = vt.getVelocity(AMOTION_EVENT_AXIS_Y, 0);
+ std::optional<float> velocityX =
+ computePlanarVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X,
+ DEFAULT_POINTER_ID);
+ std::optional<float> velocityY =
+ computePlanarVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_Y,
+ DEFAULT_POINTER_ID);
ASSERT_TRUE(velocityX);
ASSERT_TRUE(velocityY);
@@ -330,12 +312,14 @@
{30ms, {{6, 20}}},
{40ms, {{10, 30}}}};
- EXPECT_EQ(computePlanarVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X),
+ EXPECT_EQ(computePlanarVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X,
+ DEFAULT_POINTER_ID),
computePlanarVelocity(VelocityTracker::Strategy::DEFAULT, motions,
- AMOTION_EVENT_AXIS_X));
- EXPECT_EQ(computePlanarVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_Y),
+ AMOTION_EVENT_AXIS_X, DEFAULT_POINTER_ID));
+ EXPECT_EQ(computePlanarVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_Y,
+ DEFAULT_POINTER_ID),
computePlanarVelocity(VelocityTracker::Strategy::DEFAULT, motions,
- AMOTION_EVENT_AXIS_Y));
+ AMOTION_EVENT_AXIS_Y, DEFAULT_POINTER_ID));
}
TEST_F(VelocityTrackerTest, TestComputedVelocity) {
@@ -431,7 +415,7 @@
VelocityTracker vt(VelocityTracker::Strategy::IMPULSE);
std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
for (const MotionEvent& event : events) {
- vt.addMovement(&event);
+ vt.addMovement(event);
}
float maxFloat = std::numeric_limits<float>::max();
@@ -509,6 +493,89 @@
computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 500);
}
+/**
+ * When the stream is terminated with ACTION_CANCEL, the resulting velocity should be 0.
+ */
+TEST_F(VelocityTrackerTest, ActionCancelResultsInZeroVelocity) {
+ std::vector<PlanarMotionEventEntry> motions = {
+ {0ms, {{0, 0}}}, // DOWN
+ {10ms, {{5, 10}}}, // MOVE
+ {20ms, {{10, 20}}}, // MOVE
+ {20ms, {{10, 20}}}, // ACTION_UP
+ };
+ std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
+ // By default, `createTouchMotionEventStream` produces an event stream that terminates with
+ // ACTION_UP. We need to manually change it to ACTION_CANCEL.
+ MotionEvent& lastEvent = events.back();
+ lastEvent.setAction(AMOTION_EVENT_ACTION_CANCEL);
+ lastEvent.setFlags(lastEvent.getFlags() | AMOTION_EVENT_FLAG_CANCELED);
+ const int32_t pointerId = lastEvent.getPointerId(0);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::IMPULSE, events, AMOTION_EVENT_AXIS_X,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::IMPULSE, events, AMOTION_EVENT_AXIS_Y,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events, AMOTION_EVENT_AXIS_X,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events, AMOTION_EVENT_AXIS_Y,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+}
+
+/**
+ * When the stream is terminated with ACTION_CANCEL, the resulting velocity should be 0.
+ */
+TEST_F(VelocityTrackerTest, ActionPointerCancelResultsInZeroVelocityForThatPointer) {
+ std::vector<PlanarMotionEventEntry> motions = {
+ {0ms, {{0, 5}, {NAN, NAN}}}, // DOWN
+ {0ms, {{0, 5}, {10, 15}}}, // POINTER_DOWN
+ {10ms, {{5, 10}, {15, 20}}}, // MOVE
+ {20ms, {{10, 15}, {20, 25}}}, // MOVE
+ {30ms, {{10, 15}, {20, 25}}}, // POINTER_UP
+ {30ms, {{10, 15}, {NAN, NAN}}}, // UP
+ };
+ std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
+ // Cancel the lifting pointer of the ACTION_POINTER_UP event
+ MotionEvent& pointerUpEvent = events.rbegin()[1];
+ pointerUpEvent.setFlags(pointerUpEvent.getFlags() | AMOTION_EVENT_FLAG_CANCELED);
+ const int32_t pointerId = pointerUpEvent.getPointerId(pointerUpEvent.getActionIndex());
+ // Double check the stream
+ ASSERT_EQ(1, pointerId);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP, pointerUpEvent.getActionMasked());
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, events.back().getActionMasked());
+
+ // Ensure the velocity of the lifting pointer is zero
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::IMPULSE, events, AMOTION_EVENT_AXIS_X,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::IMPULSE, events, AMOTION_EVENT_AXIS_Y,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events, AMOTION_EVENT_AXIS_X,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events, AMOTION_EVENT_AXIS_Y,
+ pointerId),
+ /*targetVelocity*/ std::nullopt);
+
+ // The remaining pointer should have the correct velocity.
+ const int32_t remainingPointerId = events.back().getPointerId(0);
+ ASSERT_EQ(0, remainingPointerId);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::IMPULSE, events, AMOTION_EVENT_AXIS_X,
+ remainingPointerId),
+ /*targetVelocity*/ 500);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::IMPULSE, events, AMOTION_EVENT_AXIS_Y,
+ remainingPointerId),
+ /*targetVelocity*/ 500);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events, AMOTION_EVENT_AXIS_X,
+ remainingPointerId),
+ /*targetVelocity*/ 500);
+ checkVelocity(computeVelocity(VelocityTracker::Strategy::LSQ2, events, AMOTION_EVENT_AXIS_Y,
+ remainingPointerId),
+ /*targetVelocity*/ 500);
+}
/**
* ================== VelocityTracker tests generated by recording real events =====================
@@ -1336,9 +1403,10 @@
{40ms, 100},
};
- EXPECT_EQ(computeVelocity(VelocityTracker::Strategy::IMPULSE, motions,
+ std::vector<MotionEvent> events = createAxisScrollMotionEventStream(motions);
+ EXPECT_EQ(computeVelocity(VelocityTracker::Strategy::IMPULSE, events,
AMOTION_EVENT_AXIS_SCROLL),
- computeVelocity(VelocityTracker::Strategy::DEFAULT, motions,
+ computeVelocity(VelocityTracker::Strategy::DEFAULT, events,
AMOTION_EVENT_AXIS_SCROLL));
}
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index 32fb350..099f47d 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -19,7 +19,7 @@
#include <android/hardware_buffer.h>
#include <gui/BufferQueueDefs.h>
#include <gui/ConsumerBase.h>
-#include <gui/Flags.h>
+
#include <gui/IGraphicBufferProducer.h>
#include <sys/cdefs.h>
#include <system/graphics.h>
@@ -352,7 +352,7 @@
/**
* onSetFrameRate Notifies the consumer of a setFrameRate call from the producer side.
*/
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
void onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) override;
#endif
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index c2535e0..3a09204 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -515,7 +515,7 @@
}
}
-#if FLAG_BQ_SET_FRAME_RATE
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE)
void SurfaceTexture::onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
SFT_LOGV("onSetFrameRate: %.2f", frameRate);
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index 0eeca54..86dcaef 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -20,6 +20,12 @@
],
}
+filegroup {
+ name: "framework-permission-aidl-filegroup",
+ srcs: ["aidl/android/**/*.aidl"],
+ path: "aidl",
+}
+
cc_library {
name: "libpermission",
host_supported: true,
@@ -35,6 +41,7 @@
"-Werror",
],
srcs: [
+ ":framework-permission-aidl-filegroup",
"AppOpsManager.cpp",
"IAppOpsCallback.cpp",
"IAppOpsService.cpp",
diff --git a/libs/permission/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp
index 6959274..b407d02 100644
--- a/libs/permission/AppOpsManager.cpp
+++ b/libs/permission/AppOpsManager.cpp
@@ -31,6 +31,9 @@
namespace android {
+using ::android::String16;
+using ::android::String8;
+
static const sp<IBinder>& getClientId() {
static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER;
static sp<IBinder> gClientId;
@@ -43,6 +46,11 @@
return gClientId;
}
+
+static std::string getString(const String16& stringToConvert) {
+ return std::string(String8(stringToConvert).c_str());
+}
+
AppOpsManager::AppOpsManager()
{
}
@@ -78,9 +86,14 @@
int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
{
sp<IAppOpsService> service = getService();
- return service != nullptr
- ? service->checkOperation(op, uid, callingPackage)
- : AppOpsManager::MODE_IGNORED;
+ if (service == nullptr) {
+ return AppOpsManager::MODE_IGNORED;
+ }
+ AttributionSourceState attributionSourceState;
+ attributionSourceState.uid = uid;
+ attributionSourceState.packageName = getString(callingPackage);
+
+ return service->checkOperationWithState(op, attributionSourceState);
}
int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
@@ -99,12 +112,18 @@
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
const std::optional<String16>& attributionTag, const String16& message) {
sp<IAppOpsService> service = getService();
- int32_t mode = service != nullptr
- ? service->noteOperation(op, uid, callingPackage, attributionTag,
- shouldCollectNotes(op), message, uid == AID_SYSTEM)
- : AppOpsManager::MODE_IGNORED;
+ if (service == nullptr) {
+ return AppOpsManager::MODE_IGNORED;
+ }
+ AttributionSourceState attributionSourceState;
+ attributionSourceState.uid = uid;
+ attributionSourceState.packageName = getString(callingPackage);
+ if (attributionTag.has_value()) {
+ attributionSourceState.attributionTag = getString(attributionTag.value());
+ }
- return mode;
+ return service->noteOperationWithState(op, attributionSourceState,
+ shouldCollectNotes(op), message, uid == AID_SYSTEM);
}
int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
@@ -117,13 +136,18 @@
bool startIfModeDefault, const std::optional<String16>& attributionTag,
const String16& message) {
sp<IAppOpsService> service = getService();
- int32_t mode = service != nullptr
- ? service->startOperation(getClientId(), op, uid, callingPackage,
- attributionTag, startIfModeDefault, shouldCollectNotes(op), message,
- uid == AID_SYSTEM)
- : AppOpsManager::MODE_IGNORED;
+ if (service == nullptr) {
+ return AppOpsManager::MODE_IGNORED;
+ }
+ AttributionSourceState attributionSourceState;
+ attributionSourceState.uid = uid;
+ attributionSourceState.packageName = getString(callingPackage);
+ if (attributionTag.has_value()) {
+ attributionSourceState.attributionTag = getString(attributionTag.value());
+ }
- return mode;
+ return service->startOperationWithState(getClientId(), op, attributionSourceState,
+ startIfModeDefault,shouldCollectNotes(op), message, uid == AID_SYSTEM);
}
void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
@@ -133,9 +157,16 @@
void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage,
const std::optional<String16>& attributionTag) {
sp<IAppOpsService> service = getService();
- if (service != nullptr) {
- service->finishOperation(getClientId(), op, uid, callingPackage, attributionTag);
+ if (service == nullptr) {
+ return;
}
+ AttributionSourceState attributionSourceState;
+ attributionSourceState.uid = uid;
+ attributionSourceState.packageName = getString(callingPackage);
+ if (attributionTag.has_value()) {
+ attributionSourceState.attributionTag = getString(attributionTag.value());
+ }
+ service->finishOperationWithState(getClientId(), op, attributionSourceState);
}
void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName,
diff --git a/libs/permission/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
index 7f235a4..33dd24d 100644
--- a/libs/permission/IAppOpsService.cpp
+++ b/libs/permission/IAppOpsService.cpp
@@ -26,6 +26,8 @@
namespace android {
+using android::content::AttributionSourceState;
+
// ----------------------------------------------------------------------
class BpAppOpsService : public BpInterface<IAppOpsService>
@@ -36,31 +38,30 @@
{
}
- virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) {
+ virtual int32_t checkOperationWithState(int32_t code,
+ const AttributionSourceState &attributionSourceState) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(code);
- data.writeInt32(uid);
- data.writeString16(packageName);
- remote()->transact(CHECK_OPERATION_TRANSACTION, data, &reply);
+ data.writeParcelable(attributionSourceState);
+ remote()->transact(CHECK_OPERATION_WITH_STATE_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
return reply.readInt32();
}
- virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
- const std::optional<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
- const String16& message, bool shouldCollectMessage) {
+ virtual int32_t noteOperationWithState(int32_t code,
+ const AttributionSourceState& attributionSourceState,
+ bool shouldCollectAsyncNotedOp, const String16& message,
+ bool shouldCollectMessage) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(code);
- data.writeInt32(uid);
- data.writeString16(packageName);
- data.writeString16(attributionTag);
+ data.writeParcelable(attributionSourceState);
data.writeBool(shouldCollectAsyncNotedOp);
data.writeString16(message);
data.writeBool(shouldCollectMessage);
- remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply);
+ remote()->transact(NOTE_OPERATION_WITH_STATE_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
// TODO b/184855056: extract to class
@@ -69,22 +70,20 @@
return reply.readInt32();
}
- virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::optional<String16>& attributionTag,
- bool startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message,
+ virtual int32_t startOperationWithState(const sp<IBinder>& token, int32_t code,
+ const AttributionSourceState& attributionSourceState, bool startIfModeDefault,
+ bool shouldCollectAsyncNotedOp, const String16& message,
bool shouldCollectMessage) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(token);
data.writeInt32(code);
- data.writeInt32(uid);
- data.writeString16(packageName);
- data.writeString16(attributionTag);
+ data.writeParcelable(attributionSourceState);
data.writeBool(startIfModeDefault);
data.writeBool(shouldCollectAsyncNotedOp);
data.writeString16(message);
data.writeBool(shouldCollectMessage);
- remote()->transact(START_OPERATION_TRANSACTION, data, &reply);
+ remote()->transact(START_OPERATION_WITH_STATE_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
// TODO b/184855056: extract to class
@@ -93,16 +92,14 @@
return reply.readInt32();
}
- virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::optional<String16>& attributionTag) {
+ virtual void finishOperationWithState(const sp<IBinder>& token, int32_t code,
+ const AttributionSourceState& attributionSourceState) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(token);
data.writeInt32(code);
- data.writeInt32(uid);
- data.writeString16(packageName);
- data.writeString16(attributionTag);
- remote()->transact(FINISH_OPERATION_TRANSACTION, data, &reply);
+ data.writeParcelable(attributionSourceState);
+ remote()->transact(FINISH_OPERATION_WITH_STATE_TRANSACTION, data, &reply);
}
virtual void startWatchingMode(int32_t op, const String16& packageName,
@@ -189,59 +186,65 @@
{
//printf("AppOpsService received: "); data.print();
switch(code) {
- case CHECK_OPERATION_TRANSACTION: {
+ case CHECK_OPERATION_WITH_STATE_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
int32_t code = data.readInt32();
- int32_t uid = data.readInt32();
- String16 packageName = data.readString16();
- int32_t res = checkOperation(code, uid, packageName);
+ AttributionSourceState attributionSourceState;
+ status_t status = data.readParcelable(&attributionSourceState);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ int32_t res = checkOperationWithState(code, attributionSourceState);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
} break;
- case NOTE_OPERATION_TRANSACTION: {
+ case NOTE_OPERATION_WITH_STATE_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
int32_t code = data.readInt32();
- int32_t uid = data.readInt32();
- String16 packageName = data.readString16();
- std::optional<String16> attributionTag;
- data.readString16(&attributionTag);
+ AttributionSourceState attributionSourceState;
+ status_t status = data.readParcelable(&attributionSourceState);
+ if (status != NO_ERROR) {
+ return status;
+ }
bool shouldCollectAsyncNotedOp = data.readBool();
String16 message = data.readString16();
bool shouldCollectMessage = data.readBool();
- int32_t res = noteOperation(code, uid, packageName, attributionTag,
+ int32_t res = noteOperationWithState(code, attributionSourceState,
shouldCollectAsyncNotedOp, message, shouldCollectMessage);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
} break;
- case START_OPERATION_TRANSACTION: {
+ case START_OPERATION_WITH_STATE_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
sp<IBinder> token = data.readStrongBinder();
int32_t code = data.readInt32();
- int32_t uid = data.readInt32();
- String16 packageName = data.readString16();
- std::optional<String16> attributionTag;
- data.readString16(&attributionTag);
+ AttributionSourceState attributionSourceState;
+ status_t status = data.readParcelable(&attributionSourceState);
+ if (status != NO_ERROR) {
+ return status;
+ }
bool startIfModeDefault = data.readBool();
bool shouldCollectAsyncNotedOp = data.readBool();
String16 message = data.readString16();
bool shouldCollectMessage = data.readBool();
- int32_t res = startOperation(token, code, uid, packageName, attributionTag,
+ int32_t res = startOperationWithState(token, code, attributionSourceState,
startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
} break;
- case FINISH_OPERATION_TRANSACTION: {
+ case FINISH_OPERATION_WITH_STATE_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
sp<IBinder> token = data.readStrongBinder();
int32_t code = data.readInt32();
- int32_t uid = data.readInt32();
- String16 packageName = data.readString16();
- std::optional<String16> attributionTag;
- data.readString16(&attributionTag);
- finishOperation(token, code, uid, packageName, attributionTag);
+ AttributionSourceState attributionSourceState;
+ status_t status = data.readParcelable(&attributionSourceState);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ finishOperationWithState(token, code, attributionSourceState);
reply->writeNoException();
return NO_ERROR;
} break;
diff --git a/libs/permission/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
index 918fcdb..a5fdc54 100644
--- a/libs/permission/include/binder/IAppOpsService.h
+++ b/libs/permission/include/binder/IAppOpsService.h
@@ -16,6 +16,7 @@
#pragma once
+#include <android/content/AttributionSourceState.h>
#include <binder/IAppOpsCallback.h>
#include <binder/IInterface.h>
@@ -27,23 +28,24 @@
namespace android {
+using android::content::AttributionSourceState;
+
// ----------------------------------------------------------------------
class IAppOpsService : public IInterface
{
public:
DECLARE_META_INTERFACE(AppOpsService)
-
- virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
- virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
- const std::optional<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
+ virtual int32_t checkOperationWithState(int32_t code,
+ const AttributionSourceState& attributionSourceState) = 0;
+ virtual int32_t noteOperationWithState(int32_t code,
+ const AttributionSourceState& attributionSourceState, bool shouldCollectAsyncNotedOp,
const String16& message, bool shouldCollectMessage) = 0;
- virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::optional<String16>& attributionTag,
- bool startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message,
- bool shouldCollectMessage) = 0;
- virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
- const String16& packageName, const std::optional<String16>& attributionTag) = 0;
+ virtual int32_t startOperationWithState(const sp<IBinder>& token, int32_t code,
+ const AttributionSourceState& attributionSourceState, bool startIfModeDefault,
+ bool shouldCollectAsyncNotedOp, const String16& message, bool shouldCollectMessage) = 0;
+ virtual void finishOperationWithState(const sp<IBinder>& token, int32_t code,
+ const AttributionSourceState& attributionSourceState) = 0;
virtual void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback) = 0;
virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
@@ -56,10 +58,10 @@
int32_t flags, const sp<IAppOpsCallback>& callback) = 0;
enum {
- CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
- NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
- START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
- FINISH_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+3,
+ CHECK_OPERATION_WITH_STATE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+50,
+ NOTE_OPERATION_WITH_STATE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+52,
+ START_OPERATION_WITH_STATE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+53,
+ FINISH_OPERATION_WITH_STATE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+54,
START_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+4,
STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 04e2fff..af08a1c 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -66,6 +66,7 @@
static const char* PERSIST_DRIVER_SUFFIX_PROPERTY = "persist.graphics.egl";
static const char* RO_DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
static const char* RO_BOARD_PLATFORM_PROPERTY = "ro.board.platform";
+static const char* ANGLE_SUFFIX_VALUE = "angle";
static const char* HAL_SUBNAME_KEY_PROPERTIES[3] = {
PERSIST_DRIVER_SUFFIX_PROPERTY,
@@ -80,6 +81,13 @@
"/vendor/lib/egl";
#endif
+static const char* const SYSTEM_LIB_DIR =
+#if defined(__LP64__)
+ "/system/lib64";
+#else
+ "/system/lib";
+#endif
+
static void* do_dlopen(const char* path, int mode) {
ATRACE_CALL();
return dlopen(path, mode);
@@ -434,98 +442,108 @@
}
}
+static std::string findLibrary(const std::string libraryName, const std::string searchPath,
+ const bool exact) {
+ if (exact) {
+ std::string absolutePath = searchPath + "/" + libraryName + ".so";
+ if (!access(absolutePath.c_str(), R_OK)) {
+ return absolutePath;
+ }
+ return std::string();
+ }
+
+ DIR* d = opendir(searchPath.c_str());
+ if (d != nullptr) {
+ struct dirent* e;
+ while ((e = readdir(d)) != nullptr) {
+ if (e->d_type == DT_DIR) {
+ continue;
+ }
+ if (!strcmp(e->d_name, "libGLES_android.so")) {
+ // always skip the software renderer
+ continue;
+ }
+ if (strstr(e->d_name, libraryName.c_str()) == e->d_name) {
+ if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
+ std::string result = searchPath + "/" + e->d_name;
+ closedir(d);
+ return result;
+ }
+ }
+ }
+ closedir(d);
+ }
+ // Driver not found. gah.
+ return std::string();
+}
+
static void* load_system_driver(const char* kind, const char* suffix, const bool exact) {
ATRACE_CALL();
- class MatchFile {
- public:
- static std::string find(const char* libraryName, const bool exact) {
- std::string absolutePath;
- if (findLibPath(absolutePath, libraryName, exact)) {
- return absolutePath;
- }
-
- // Driver not found. gah.
- return std::string();
- }
- private:
- static bool findLibPath(std::string& result, const std::string& pattern, bool exact) {
- const std::string vendorLibEglDirString = std::string(VENDOR_LIB_EGL_DIR);
- if (exact) {
- std::string absolutePath = vendorLibEglDirString + "/" + pattern + ".so";
- if (!access(absolutePath.c_str(), R_OK)) {
- result = absolutePath;
- return true;
- }
- return false;
- }
-
- DIR* d = opendir(VENDOR_LIB_EGL_DIR);
- if (d != nullptr) {
- struct dirent* e;
- while ((e = readdir(d)) != nullptr) {
- if (e->d_type == DT_DIR) {
- continue;
- }
- if (!strcmp(e->d_name, "libGLES_android.so")) {
- // always skip the software renderer
- continue;
- }
- if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
- if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
- result = vendorLibEglDirString + "/" + e->d_name;
- closedir(d);
- return true;
- }
- }
- }
- closedir(d);
- }
- return false;
- }
- };
std::string libraryName = std::string("lib") + kind;
if (suffix) {
libraryName += std::string("_") + suffix;
} else if (!exact) {
- // Deprecated: we look for files that match
- // libGLES_*.so, or:
+ // Deprecated for devices launching in Android 14
+ // Look for files that match
+ // libGLES_*.so, or,
// libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
libraryName += std::string("_");
}
- std::string absolutePath = MatchFile::find(libraryName.c_str(), exact);
+
+ void* dso = nullptr;
+
+ // Only use sphal namespace when system ANGLE binaries are not the default drivers.
+ const bool useSphalNamespace = suffix != nullptr && strcmp(suffix, ANGLE_SUFFIX_VALUE) != 0;
+
+ const std::string absolutePath =
+ findLibrary(libraryName, useSphalNamespace ? VENDOR_LIB_EGL_DIR : SYSTEM_LIB_PATH,
+ exact);
if (absolutePath.empty()) {
// this happens often, we don't want to log an error
return nullptr;
}
- const char* const driver_absolute_path = absolutePath.c_str();
+ const char* const driverAbsolutePath = absolutePath.c_str();
- // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
- // the original routine when the namespace does not exist.
- // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
- // sphal namespace.
- void* dso = do_android_load_sphal_library(driver_absolute_path,
- RTLD_NOW | RTLD_LOCAL);
+ // Currently the default driver is unlikely to be ANGLE on most devices,
+ // hence put this first.
+ if (useSphalNamespace) {
+ // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
+ // the original routine when the namespace does not exist.
+ // See /system/linkerconfig/contents/namespace for the configuration of the
+ // sphal namespace.
+ dso = do_android_load_sphal_library(driverAbsolutePath, RTLD_NOW | RTLD_LOCAL);
+ } else {
+ // Try to load drivers from the default namespace.
+ // See /system/linkerconfig/contents/namespace for the configuration of the
+ // default namespace.
+ dso = do_dlopen(driverAbsolutePath, RTLD_NOW | RTLD_LOCAL);
+ }
+
if (dso == nullptr) {
const char* err = dlerror();
- ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
+ ALOGE("load_driver(%s): %s", driverAbsolutePath, err ? err : "unknown");
return nullptr;
}
- ALOGD("loaded %s", driver_absolute_path);
+ ALOGV("loaded %s", driverAbsolutePath);
return dso;
}
static void* load_angle(const char* kind, android_namespace_t* ns) {
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = ns,
- };
-
std::string name = std::string("lib") + kind + "_angle.so";
+ void* so = nullptr;
- void* so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ if (android::GraphicsEnv::getInstance().shouldUseSystemAngle()) {
+ so = do_dlopen(name.c_str(), RTLD_NOW | RTLD_LOCAL);
+ } else {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = ns,
+ };
+ so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ }
if (so) {
return so;
@@ -563,10 +581,14 @@
ATRACE_CALL();
android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
- if (!ns) {
+ // ANGLE namespace is used for loading ANGLE from apk, and hence if namespace is not
+ // constructed, it means ANGLE apk is not set to be the OpenGL ES driver.
+ // Hence skip if ANGLE apk and system ANGLE are not set to be the OpenGL ES driver.
+ if (!ns && !android::GraphicsEnv::getInstance().shouldUseSystemAngle()) {
return nullptr;
}
+ // use ANGLE APK driver
android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
driver_t* hnd = nullptr;
@@ -592,6 +614,7 @@
if (pANGLEGetDisplayPlatform) {
ALOGV("ANGLE GLES library loaded");
cnx->angleLoaded = true;
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
} else {
ALOGV("Native GLES library loaded");
cnx->angleLoaded = false;
@@ -635,7 +658,13 @@
Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
const bool exact) {
ATRACE_CALL();
- android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+ if (suffix && strcmp(suffix, "angle") == 0) {
+ // use system ANGLE driver
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
+ } else {
+ android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
+ }
+
driver_t* hnd = nullptr;
void* dso = load_system_driver("GLES", suffix, exact);
if (dso) {
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index ee605c2..a8395d9 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -128,8 +128,8 @@
return false;
}
} else {
- // If we are here, ANGLE is loaded as built-in gl driver in the sphal.
- so = android_load_sphal_library(kAngleEs2Lib, kAngleDlFlags);
+ // If we are here, ANGLE is loaded as the default OpenGL ES driver.
+ so = dlopen(kAngleEs2Lib, kAngleDlFlags);
if (so) {
ALOGD("dlopen (%s) success at %p", kAngleEs2Lib, so);
} else {
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index f06a045..11b636d 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -163,11 +163,13 @@
addLoadingTime(driver, driverLoadingTime, &appInfo);
appInfo.appPackageName = appPackageName;
appInfo.driverVersionCode = driverVersionCode;
- appInfo.angleInUse = driverPackageName == "angle";
+ appInfo.angleInUse =
+ driver == GpuStatsInfo::Driver::ANGLE || driverPackageName == "angle";
appInfo.lastAccessTime = std::chrono::system_clock::now();
mAppStats.insert({appStatsKey, appInfo});
} else {
- mAppStats[appStatsKey].angleInUse = driverPackageName == "angle";
+ mAppStats[appStatsKey].angleInUse =
+ driver == GpuStatsInfo::Driver::ANGLE || driverPackageName == "angle";
addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
mAppStats[appStatsKey].lastAccessTime = std::chrono::system_clock::now();
}
diff --git a/services/inputflinger/PreferStylusOverTouchBlocker.cpp b/services/inputflinger/PreferStylusOverTouchBlocker.cpp
index ee0ab33..d9d0450 100644
--- a/services/inputflinger/PreferStylusOverTouchBlocker.cpp
+++ b/services/inputflinger/PreferStylusOverTouchBlocker.cpp
@@ -15,10 +15,15 @@
*/
#include "PreferStylusOverTouchBlocker.h"
+#include <com_android_input_flags.h>
#include <input/PrintTools.h>
+namespace input_flags = com::android::input::flags;
+
namespace android {
+const bool BLOCK_TOUCH_WHEN_STYLUS_HOVER = !input_flags::disable_reject_touch_on_stylus_hover();
+
static std::pair<bool, bool> checkToolType(const NotifyMotionArgs& args) {
bool hasStylus = false;
bool hasTouch = false;
@@ -96,8 +101,11 @@
std::vector<NotifyMotionArgs> PreferStylusOverTouchBlocker::processMotion(
const NotifyMotionArgs& args) {
const auto [hasTouch, hasStylus] = checkToolType(args);
- const bool isUpOrCancel =
- args.action == AMOTION_EVENT_ACTION_UP || args.action == AMOTION_EVENT_ACTION_CANCEL;
+ const bool isDisengageOrCancel = BLOCK_TOUCH_WHEN_STYLUS_HOVER
+ ? (args.action == AMOTION_EVENT_ACTION_HOVER_EXIT ||
+ args.action == AMOTION_EVENT_ACTION_UP || args.action == AMOTION_EVENT_ACTION_CANCEL)
+ : (args.action == AMOTION_EVENT_ACTION_UP ||
+ args.action == AMOTION_EVENT_ACTION_CANCEL);
if (hasTouch && hasStylus) {
mDevicesWithMixedToolType.insert(args.deviceId);
@@ -109,7 +117,7 @@
if (mCanceledDevices.find(args.deviceId) != mCanceledDevices.end()) {
// If we started to cancel events from this device, continue to do so to keep
// the stream consistent. It should happen at most once per "mixed" device.
- if (isUpOrCancel) {
+ if (isDisengageOrCancel) {
mCanceledDevices.erase(args.deviceId);
mLastTouchEvents.erase(args.deviceId);
}
@@ -119,10 +127,13 @@
}
const bool isStylusEvent = hasStylus;
- const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
+ const bool isEngage = BLOCK_TOUCH_WHEN_STYLUS_HOVER
+ ? (args.action == AMOTION_EVENT_ACTION_DOWN ||
+ args.action == AMOTION_EVENT_ACTION_HOVER_ENTER)
+ : (args.action == AMOTION_EVENT_ACTION_DOWN);
if (isStylusEvent) {
- if (isDown) {
+ if (isEngage) {
// Reject all touch while stylus is down
mActiveStyli.insert(args.deviceId);
@@ -143,7 +154,7 @@
result.push_back(args);
return result;
}
- if (isUpOrCancel) {
+ if (isDisengageOrCancel) {
mActiveStyli.erase(args.deviceId);
}
// Never drop stylus events
@@ -158,7 +169,7 @@
}
const bool shouldDrop = mCanceledDevices.find(args.deviceId) != mCanceledDevices.end();
- if (isUpOrCancel) {
+ if (isDisengageOrCancel) {
mCanceledDevices.erase(args.deviceId);
mLastTouchEvents.erase(args.deviceId);
}
@@ -169,7 +180,7 @@
return {};
}
- if (!isUpOrCancel) {
+ if (!isDisengageOrCancel) {
mLastTouchEvents[args.deviceId] = args;
}
return {args};
diff --git a/services/inputflinger/dispatcher/DebugConfig.h b/services/inputflinger/dispatcher/DebugConfig.h
index c7d98ab..c889b9b 100644
--- a/services/inputflinger/dispatcher/DebugConfig.h
+++ b/services/inputflinger/dispatcher/DebugConfig.h
@@ -69,6 +69,16 @@
android::base::ShouldLog(android::base::LogSeverity::DEBUG, LOG_TAG "Injection");
/**
+ * Generally, we always log whenever events are dropped. However, to reduce logspam, some messages
+ * are suppressed.
+ * Log additional debug messages about dropped input events with this flag.
+ * Enable this via "adb shell setprop log.tag.InputDispatcherDroppedEventsVerbose DEBUG".
+ * Requires system_server restart via `adb shell stop && adb shell start`.
+ */
+const bool DEBUG_DROPPED_EVENTS_VERBOSE =
+ android::base::ShouldLog(android::base::LogSeverity::DEBUG, LOG_TAG "DroppedEventsVerbose");
+
+/**
* Log debug messages about input focus tracking.
* Enable this via "adb shell setprop log.tag.InputDispatcherFocus DEBUG" (requires restart)
*/
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 53e0855..156697a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -72,6 +72,8 @@
using android::os::InputEventInjectionSync;
namespace input_flags = com::android::input::flags;
+static const bool REMOVE_APP_SWITCH_DROPS = input_flags::remove_app_switch_drops();
+
namespace android::inputdispatcher {
namespace {
@@ -756,10 +758,6 @@
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy)
- : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {}
-
-InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
- std::chrono::nanoseconds staleEventTimeout)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
@@ -774,7 +772,6 @@
mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
- mStaleEventTimeout(staleEventTimeout),
mLatencyAggregator(),
mLatencyTracker(&mLatencyAggregator) {
mLooper = sp<Looper>::make(false);
@@ -956,20 +953,25 @@
// Optimize latency of app switches.
// Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
// been pressed. When it expires, we preempt dispatch and drop all other pending events.
- bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
- if (mAppSwitchDueTime < *nextWakeupTime) {
- *nextWakeupTime = mAppSwitchDueTime;
+ bool isAppSwitchDue;
+ if (!REMOVE_APP_SWITCH_DROPS) {
+ isAppSwitchDue = mAppSwitchDueTime <= currentTime;
+ if (mAppSwitchDueTime < *nextWakeupTime) {
+ *nextWakeupTime = mAppSwitchDueTime;
+ }
}
// Ready to start a new event.
// If we don't already have a pending event, go grab one.
if (!mPendingEvent) {
if (mInboundQueue.empty()) {
- if (isAppSwitchDue) {
- // The inbound queue is empty so the app switch key we were waiting
- // for will never arrive. Stop waiting for it.
- resetPendingAppSwitchLocked(false);
- isAppSwitchDue = false;
+ if (!REMOVE_APP_SWITCH_DROPS) {
+ if (isAppSwitchDue) {
+ // The inbound queue is empty so the app switch key we were waiting
+ // for will never arrive. Stop waiting for it.
+ resetPendingAppSwitchLocked(false);
+ isAppSwitchDue = false;
+ }
}
// Synthesize a key repeat if appropriate.
@@ -1067,12 +1069,14 @@
case EventEntry::Type::KEY: {
std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
- if (isAppSwitchDue) {
- if (isAppSwitchKeyEvent(*keyEntry)) {
- resetPendingAppSwitchLocked(true);
- isAppSwitchDue = false;
- } else if (dropReason == DropReason::NOT_DROPPED) {
- dropReason = DropReason::APP_SWITCH;
+ if (!REMOVE_APP_SWITCH_DROPS) {
+ if (isAppSwitchDue) {
+ if (isAppSwitchKeyEvent(*keyEntry)) {
+ resetPendingAppSwitchLocked(true);
+ isAppSwitchDue = false;
+ } else if (dropReason == DropReason::NOT_DROPPED) {
+ dropReason = DropReason::APP_SWITCH;
+ }
}
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *keyEntry)) {
@@ -1088,8 +1092,10 @@
case EventEntry::Type::MOTION: {
std::shared_ptr<MotionEntry> motionEntry =
std::static_pointer_cast<MotionEntry>(mPendingEvent);
- if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
- dropReason = DropReason::APP_SWITCH;
+ if (!REMOVE_APP_SWITCH_DROPS) {
+ if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
+ dropReason = DropReason::APP_SWITCH;
+ }
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
dropReason = DropReason::STALE;
@@ -1104,8 +1110,10 @@
case EventEntry::Type::SENSOR: {
std::shared_ptr<SensorEntry> sensorEntry =
std::static_pointer_cast<SensorEntry>(mPendingEvent);
- if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
- dropReason = DropReason::APP_SWITCH;
+ if (!REMOVE_APP_SWITCH_DROPS) {
+ if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
+ dropReason = DropReason::APP_SWITCH;
+ }
}
// Sensor timestamps use SYSTEM_TIME_BOOTTIME time base, so we can't use
// 'currentTime' here, get SYSTEM_TIME_BOOTTIME instead.
@@ -1131,7 +1139,7 @@
}
bool InputDispatcher::isStaleEvent(nsecs_t currentTime, const EventEntry& entry) {
- return std::chrono::nanoseconds(currentTime - entry.eventTime) >= mStaleEventTimeout;
+ return mPolicy.isStaleEvent(currentTime, entry.eventTime);
}
/**
@@ -1207,21 +1215,23 @@
// If the application takes too long to catch up then we drop all events preceding
// the app switch key.
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
- if (isAppSwitchKeyEvent(keyEntry)) {
- if (keyEntry.action == AKEY_EVENT_ACTION_DOWN) {
- mAppSwitchSawKeyDown = true;
- } else if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
- if (mAppSwitchSawKeyDown) {
- if (DEBUG_APP_SWITCH) {
- ALOGD("App switch is pending!");
+
+ if (!REMOVE_APP_SWITCH_DROPS) {
+ if (isAppSwitchKeyEvent(keyEntry)) {
+ if (keyEntry.action == AKEY_EVENT_ACTION_DOWN) {
+ mAppSwitchSawKeyDown = true;
+ } else if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
+ if (mAppSwitchSawKeyDown) {
+ if (DEBUG_APP_SWITCH) {
+ ALOGD("App switch is pending!");
+ }
+ mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
+ mAppSwitchSawKeyDown = false;
+ needWake = true;
}
- mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
- mAppSwitchSawKeyDown = false;
- needWake = true;
}
}
}
-
// If a new up event comes in, and the pending event with same key code has been asked
// to try again later because of the policy. We have to reset the intercept key wake up
// time for it may have been handled in the policy and could be dropped.
@@ -2032,10 +2042,10 @@
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
} else {
- if (DEBUG_FOCUS) {
- ALOGD("Dropping event delivery to target with channel '%s' because it "
- "is no longer registered with the input dispatcher.",
- inputTarget.inputChannel->getName().c_str());
+ if (DEBUG_DROPPED_EVENTS_VERBOSE) {
+ LOG(INFO) << "Dropping event delivery to target with channel "
+ << inputTarget.inputChannel->getName()
+ << " because it is no longer registered with the input dispatcher.";
}
}
}
@@ -2453,10 +2463,11 @@
// If the pointer is not currently down, then ignore the event.
if (!tempTouchState.isDown(entry.deviceId) &&
maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
- LOG(INFO) << "Dropping event because the pointer for device " << entry.deviceId
- << " is not down or we previously "
- "dropped the pointer down event in display "
- << displayId << ": " << entry.getDescription();
+ if (DEBUG_DROPPED_EVENTS_VERBOSE) {
+ LOG(INFO) << "Dropping event because the pointer for device " << entry.deviceId
+ << " is not down or we previously dropped the pointer down event in "
+ << "display " << displayId << ": " << entry.getDescription();
+ }
outInjectionResult = InputEventInjectionResult::FAILED;
return {};
}
@@ -2864,8 +2875,13 @@
it = inputTargets.end() - 1;
}
- LOG_ALWAYS_FATAL_IF(it->flags != targetFlags);
- LOG_ALWAYS_FATAL_IF(it->globalScaleFactor != windowInfo->globalScaleFactor);
+ if (it->flags != targetFlags) {
+ LOG(ERROR) << "Flags don't match! targetFlags=" << targetFlags.string() << ", it=" << *it;
+ }
+ if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
+ LOG(ERROR) << "Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
+ << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
+ }
}
void InputDispatcher::addPointerWindowTargetLocked(
@@ -2911,10 +2927,12 @@
}
if (it->flags != targetFlags) {
- logDispatchStateLocked();
- LOG(FATAL) << "Flags don't match! targetFlags=" << targetFlags.string() << ", it=" << *it;
+ LOG(ERROR) << "Flags don't match! targetFlags=" << targetFlags.string() << ", it=" << *it;
}
- LOG_ALWAYS_FATAL_IF(it->globalScaleFactor != windowInfo->globalScaleFactor);
+ if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
+ LOG(ERROR) << "Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
+ << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
+ }
it->addPointers(pointerIds, windowInfo->transform);
}
@@ -4422,7 +4440,8 @@
const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
if (touchStateIt != mTouchStatesByDisplay.end()) {
const TouchState& touchState = touchStateIt->second;
- if (touchState.hasTouchingPointers(args.deviceId)) {
+ if (touchState.hasTouchingPointers(args.deviceId) ||
+ touchState.hasHoveringPointers(args.deviceId)) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
@@ -4534,6 +4553,7 @@
}
void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
+ // TODO(b/308677868) Remove device reset from the InputListener interface
if (debugInboundEventDetails()) {
ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args.eventTime,
args.deviceId);
@@ -4675,6 +4695,30 @@
}
mLock.lock();
+
+ if (policyFlags & POLICY_FLAG_FILTERED) {
+ // The events from InputFilter impersonate real hardware devices. Check these
+ // events for consistency and print an error. An inconsistent event sent from
+ // InputFilter could cause a crash in the later stages of dispatching pipeline.
+ auto [it, _] =
+ mInputFilterVerifiersByDisplay
+ .try_emplace(displayId,
+ StringPrintf("Injection on %" PRId32, displayId));
+ InputVerifier& verifier = it->second;
+
+ Result<void> result =
+ verifier.processMovement(resolvedDeviceId, motionEvent.getSource(),
+ motionEvent.getAction(),
+ motionEvent.getPointerCount(),
+ motionEvent.getPointerProperties(),
+ motionEvent.getSamplePointerCoords(), flags);
+ if (!result.ok()) {
+ logDispatchStateLocked();
+ LOG(ERROR) << "Inconsistent event: " << motionEvent
+ << ", reason: " << result.error();
+ }
+ }
+
const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
const size_t pointerCount = motionEvent.getPointerCount();
const std::vector<PointerProperties>
@@ -5800,6 +5844,9 @@
dump += INDENT "Connections: <none>\n";
}
+ dump += "input_flags::remove_app_switch_drops() = ";
+ dump += toString(REMOVE_APP_SWITCH_DROPS);
+ dump += "\n";
if (isAppSwitchPendingLocked()) {
dump += StringPrintf(INDENT "AppSwitch: pending, due in %" PRId64 "ms\n",
ns2ms(mAppSwitchDueTime - now()));
@@ -6736,6 +6783,7 @@
// Remove the associated touch mode state.
mTouchModePerDisplay.erase(displayId);
mVerifiersByDisplay.erase(displayId);
+ mInputFilterVerifiersByDisplay.erase(displayId);
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index a1127a0..e428c4e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -82,8 +82,6 @@
static constexpr bool kDefaultInTouchMode = true;
explicit InputDispatcher(InputDispatcherPolicyInterface& policy);
- explicit InputDispatcher(InputDispatcherPolicyInterface& policy,
- std::chrono::nanoseconds staleEventTimeout);
~InputDispatcher() override;
void dump(std::string& dump) const override;
@@ -288,7 +286,8 @@
void transformMotionEntryForInjectionLocked(MotionEntry&,
const ui::Transform& injectedTransform) const
REQUIRES(mLock);
-
+ // Per-display correction of injected events
+ std::map</*displayId*/ int32_t, InputVerifier> mInputFilterVerifiersByDisplay GUARDED_BY(mLock);
std::condition_variable mInjectionSyncFinished;
void incrementPendingForegroundDispatches(EventEntry& entry);
void decrementPendingForegroundDispatches(EventEntry& entry);
@@ -461,9 +460,6 @@
*/
std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock);
- // Amount of time to allow for an event to be dispatched (measured since its eventTime)
- // before considering it stale and dropping it.
- const std::chrono::nanoseconds mStaleEventTimeout;
bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry);
bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index af28e48..bf48804 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -18,6 +18,7 @@
#include "InputDispatcherConfiguration.h"
+#include <android-base/properties.h>
#include <binder/IBinder.h>
#include <gui/InputApplication.h>
#include <input/Input.h>
@@ -118,6 +119,16 @@
/* Poke user activity for an event dispatched to a window. */
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) = 0;
+ /*
+ * Return true if the provided event is stale, and false otherwise. Used for determining
+ * whether the dispatcher should drop the event.
+ */
+ virtual bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) {
+ static const std::chrono::duration STALE_EVENT_TIMEOUT =
+ std::chrono::seconds(10) * android::base::HwTimeoutMultiplier();
+ return std::chrono::nanoseconds(currentTime - eventTime) >= STALE_EVENT_TIMEOUT;
+ }
+
/* Notifies the policy that a pointer down event has occurred outside the current focused
* window.
*
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 5766b14..0582649 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -1046,6 +1046,14 @@
return mReader->mPreventingTouchpadTaps;
}
+void InputReader::ContextImpl::setLastKeyDownTimestamp(nsecs_t when) {
+ mReader->mLastKeyDownTimestamp = when;
+}
+
+nsecs_t InputReader::ContextImpl::getLastKeyDownTimestamp() {
+ return mReader->mLastKeyDownTimestamp;
+}
+
void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
// lock is already held by the input loop
mReader->disableVirtualKeysUntilLocked(time);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 9a297c9..4c78db3 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -158,6 +158,9 @@
void setPreventingTouchpadTaps(bool prevent) REQUIRES(mReader->mLock)
REQUIRES(mLock) override;
bool isPreventingTouchpadTaps() REQUIRES(mReader->mLock) REQUIRES(mLock) override;
+ void setLastKeyDownTimestamp(nsecs_t when) REQUIRES(mReader->mLock)
+ REQUIRES(mLock) override;
+ nsecs_t getLastKeyDownTimestamp() REQUIRES(mReader->mLock) REQUIRES(mLock) override;
} mContext;
friend class ContextImpl;
@@ -198,6 +201,9 @@
// true if tap-to-click on touchpad currently disabled
bool mPreventingTouchpadTaps GUARDED_BY(mLock){false};
+ // records timestamp of the last key press on the physical keyboard
+ nsecs_t mLastKeyDownTimestamp GUARDED_BY(mLock){0};
+
// low-level input event decoding and device management
[[nodiscard]] std::list<NotifyArgs> processEventsLocked(const RawEvent* rawEvents, size_t count)
REQUIRES(mLock);
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index aed7563..69b2315 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -65,6 +65,9 @@
virtual void setPreventingTouchpadTaps(bool prevent) = 0;
virtual bool isPreventingTouchpadTaps() = 0;
+
+ virtual void setLastKeyDownTimestamp(nsecs_t when) = 0;
+ virtual nsecs_t getLastKeyDownTimestamp() = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 531fc67..f068cc8 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -270,7 +270,7 @@
keyDown.flags = flags;
mKeyDowns.push_back(keyDown);
}
- onKeyDownProcessed();
+ onKeyDownProcessed(downTime);
} else {
// Remove key down.
if (keyDownIndex) {
@@ -448,8 +448,9 @@
return out;
}
-void KeyboardInputMapper::onKeyDownProcessed() {
+void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) {
InputReaderContext& context = *getContext();
+ context.setLastKeyDownTimestamp(downTime);
if (context.isPreventingTouchpadTaps()) {
// avoid pinging java service unnecessarily, just fade pointer again if it became visible
context.fadePointer();
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 09808df..500256b 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -107,7 +107,7 @@
void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset);
std::optional<DisplayViewport> findViewport(const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when);
- void onKeyDownProcessed();
+ void onKeyDownProcessed(nsecs_t downTime);
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
index f70be72..b0fc903 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
@@ -152,6 +152,14 @@
}
}
+size_t MultiTouchMotionAccumulator::getActiveSlotsCount() const {
+ if (!mUsingSlotsProtocol) {
+ return mCurrentSlot < 0 ? 0 : mCurrentSlot;
+ }
+ return std::count_if(mSlots.begin(), mSlots.end(),
+ [](const Slot& slot) { return slot.mInUse; });
+}
+
// --- MultiTouchMotionAccumulator::Slot ---
ToolType MultiTouchMotionAccumulator::Slot::getToolType() const {
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
index 943dde5..0e3e2bb 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
@@ -77,6 +77,7 @@
void process(const RawEvent* rawEvent);
void finishSync();
+ size_t getActiveSlotsCount() const;
inline size_t getSlotCount() const { return mSlots.size(); }
inline const Slot& getSlot(size_t index) const {
LOG_ALWAYS_FATAL_IF(index < 0 || index >= mSlots.size(), "Invalid index: %zu", index);
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 64e8825..db31ded 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -58,6 +58,7 @@
"InputReader_test.cpp",
"InstrumentedInputReader.cpp",
"LatencyTracker_test.cpp",
+ "MultiTouchMotionAccumulator_test.cpp",
"NotifyArgs_test.cpp",
"PointerChoreographer_test.cpp",
"PreferStylusOverTouch_test.cpp",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3c87f71..2509c60 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -112,8 +112,6 @@
// An arbitrary pid of the gesture monitor window
static constexpr gui::Pid MONITOR_PID{2001};
-static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
-
/**
* If we expect to receive the event, the timeout can be made very long. When the test are running
* correctly, we will actually never wait until the end of the timeout because the wait will end
@@ -348,6 +346,8 @@
mInterceptKeyTimeout = timeout;
}
+ void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
+
void assertUserActivityPoked() {
std::scoped_lock lock(mLock);
ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
@@ -391,6 +391,8 @@
std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
+ std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
+
BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
// All three ANR-related callbacks behave the same way, so we use this generic function to wait
@@ -545,6 +547,10 @@
mPokedUserActivity = true;
}
+ bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
+ return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
+ }
+
void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
std::scoped_lock lock(mLock);
mOnPointerDownToken = newToken;
@@ -586,7 +592,8 @@
void SetUp() override {
mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
- mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
+ mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
+
mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
// Start InputDispatcher thread
ASSERT_EQ(OK, mDispatcher->start());
@@ -2160,6 +2167,69 @@
}
/**
+ * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
+ * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
+ * interactive, it might stop sending this flag.
+ * We've already ensured the consistency of the touch event in this case, and we should also ensure
+ * the consistency of the hover event in this case.
+ *
+ * Test procedure:
+ * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
+ * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
+ *
+ * We expect to receive two full streams of hover events.
+ */
+TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+
+ sp<FakeWindowHandle> window =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 300, 300));
+
+ mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
+ .build());
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
+ .build());
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
+
+ // Send hover exit without the default policy flags.
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
+ .policyFlags(0)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
+ .build());
+
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
+
+ // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
+ // right event.
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
+ .build());
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
+ .build());
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
+ .policyFlags(DEFAULT_POLICY_FLAGS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
+ .build());
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
+}
+
+/**
* Two windows: a window on the left and a window on the right.
* Mouse is hovered from the right window into the left window.
* Next, we tap on the left window, where the cursor was last seen.
@@ -7529,6 +7599,8 @@
mWindow->consumeFocusEvent(false);
KeyEvent event;
+ static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
+ mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index dac4ea0..787444c 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -80,9 +80,15 @@
}
std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) {
+ nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+ return process(when, type, code, value);
+}
+
+std::list<NotifyArgs> InputMapperUnitTest::process(nsecs_t when, int32_t type, int32_t code,
+ int32_t value) {
RawEvent event;
- event.when = systemTime(SYSTEM_TIME_MONOTONIC);
- event.readTime = event.when;
+ event.when = when;
+ event.readTime = when;
event.deviceId = mMapper->getDeviceContext().getEventHubId();
event.type = type;
event.code = code;
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index c2ac258..3f9061f 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -52,6 +52,7 @@
void setKeyCodeState(KeyState state, std::set<int> keyCodes);
std::list<NotifyArgs> process(int32_t type, int32_t code, int32_t value);
+ std::list<NotifyArgs> process(nsecs_t when, int32_t type, int32_t code, int32_t value);
MockEventHubInterface mMockEventHub;
std::shared_ptr<FakePointerController> mFakePointerController;
diff --git a/services/inputflinger/tests/InstrumentedInputReader.h b/services/inputflinger/tests/InstrumentedInputReader.h
index ca85558..e9c7bb4 100644
--- a/services/inputflinger/tests/InstrumentedInputReader.h
+++ b/services/inputflinger/tests/InstrumentedInputReader.h
@@ -106,6 +106,9 @@
void setPreventingTouchpadTaps(bool prevent) override { mPreventingTouchpadTaps = prevent; }
bool isPreventingTouchpadTaps() override { return mPreventingTouchpadTaps; }
+ void setLastKeyDownTimestamp(nsecs_t when) override { mLastKeyDownTimestamp = when; };
+ nsecs_t getLastKeyDownTimestamp() override { return mLastKeyDownTimestamp; };
+
private:
int32_t mGlobalMetaState;
bool mUpdateGlobalMetaStateWasCalled;
@@ -113,6 +116,7 @@
std::optional<nsecs_t> mRequestedTimeout;
std::vector<InputDeviceInfo> mExternalStylusDevices;
bool mPreventingTouchpadTaps{false};
+ nsecs_t mLastKeyDownTimestamp;
} mFakeContext;
friend class InputReaderTest;
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index 05823cd..7394913 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -77,6 +77,9 @@
MOCK_METHOD(void, setPreventingTouchpadTaps, (bool prevent), (override));
MOCK_METHOD(bool, isPreventingTouchpadTaps, (), (override));
+ MOCK_METHOD(void, setLastKeyDownTimestamp, (nsecs_t when));
+ MOCK_METHOD(nsecs_t, getLastKeyDownTimestamp, ());
+
private:
int32_t mGeneration = 0;
};
diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
index 48f5673..2ef7999 100644
--- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp
+++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
@@ -26,6 +26,7 @@
namespace android {
using testing::_;
+using testing::Args;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
@@ -158,4 +159,18 @@
testTouchpadTapStateForKeys(metaKeys, /* expectPrevent= */ false);
}
+TEST_F(KeyboardInputMapperUnitTest, KeyPressTimestampRecorded) {
+ nsecs_t when = ARBITRARY_TIME;
+ std::vector<int32_t> keyCodes{KEY_0, KEY_A, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTSHIFT};
+ EXPECT_CALL(mMockInputReaderContext, setLastKeyDownTimestamp)
+ .With(Args<0>(when))
+ .Times(keyCodes.size());
+ for (int32_t keyCode : keyCodes) {
+ process(when, EV_KEY, keyCode, 1);
+ process(when, EV_SYN, SYN_REPORT, 0);
+ process(when, EV_KEY, keyCode, 0);
+ process(when, EV_SYN, SYN_REPORT, 0);
+ }
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
new file mode 100644
index 0000000..9fa6cdd
--- /dev/null
+++ b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MultiTouchMotionAccumulator.h"
+#include "InputMapperTest.h"
+
+namespace android {
+
+class MultiTouchMotionAccumulatorTest : public InputMapperUnitTest {
+protected:
+ static constexpr size_t SLOT_COUNT = 8;
+
+ MultiTouchMotionAccumulator mMotionAccumulator;
+
+ void processMotionEvent(int32_t type, int32_t code, int32_t value) {
+ RawEvent event;
+ event.when = ARBITRARY_TIME;
+ event.readTime = READ_TIME;
+ event.deviceId = EVENTHUB_ID;
+ event.type = type;
+ event.code = code;
+ event.value = value;
+ mMotionAccumulator.process(&event);
+ }
+};
+
+TEST_F(MultiTouchMotionAccumulatorTest, ActiveSlotCountUsingSlotsProtocol) {
+ mMotionAccumulator.configure(*mDeviceContext, SLOT_COUNT, /*usingSlotsProtocol=*/true);
+ // We expect active slot count to match the touches being tracked
+ // first touch
+ processMotionEvent(EV_ABS, ABS_MT_SLOT, 0);
+ processMotionEvent(EV_ABS, ABS_MT_TRACKING_ID, 123);
+ processMotionEvent(EV_SYN, SYN_REPORT, 0);
+ ASSERT_EQ(1u, mMotionAccumulator.getActiveSlotsCount());
+
+ // second touch
+ processMotionEvent(EV_ABS, ABS_MT_SLOT, 1);
+ processMotionEvent(EV_ABS, ABS_MT_TRACKING_ID, 456);
+ processMotionEvent(EV_SYN, SYN_REPORT, 0);
+ ASSERT_EQ(2u, mMotionAccumulator.getActiveSlotsCount());
+
+ // second lifted
+ processMotionEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processMotionEvent(EV_SYN, SYN_REPORT, 0);
+ ASSERT_EQ(1u, mMotionAccumulator.getActiveSlotsCount());
+
+ // first lifted
+ processMotionEvent(EV_ABS, ABS_MT_SLOT, 0);
+ processMotionEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processMotionEvent(EV_SYN, SYN_REPORT, 0);
+ ASSERT_EQ(0u, mMotionAccumulator.getActiveSlotsCount());
+}
+
+TEST_F(MultiTouchMotionAccumulatorTest, ActiveSlotCountNotUsingSlotsProtocol) {
+ mMotionAccumulator.configure(*mDeviceContext, SLOT_COUNT, /*usingSlotsProtocol=*/false);
+
+ // first touch
+ processMotionEvent(EV_ABS, ABS_MT_POSITION_X, 0);
+ processMotionEvent(EV_ABS, ABS_MT_POSITION_Y, 0);
+ processMotionEvent(EV_SYN, SYN_MT_REPORT, 0);
+ ASSERT_EQ(1u, mMotionAccumulator.getActiveSlotsCount());
+
+ // second touch
+ processMotionEvent(EV_ABS, ABS_MT_POSITION_X, 50);
+ processMotionEvent(EV_ABS, ABS_MT_POSITION_Y, 50);
+ processMotionEvent(EV_SYN, SYN_MT_REPORT, 0);
+ ASSERT_EQ(2u, mMotionAccumulator.getActiveSlotsCount());
+
+ // reset
+ mMotionAccumulator.finishSync();
+ ASSERT_EQ(0u, mMotionAccumulator.getActiveSlotsCount());
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index bdedfdf..e1c0fe2 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -360,6 +360,12 @@
void setPreventingTouchpadTaps(bool prevent) {}
bool isPreventingTouchpadTaps() { return mFdp->ConsumeBool(); };
+
+ void setLastKeyDownTimestamp(nsecs_t when) { mLastKeyDownTimestamp = when; };
+ nsecs_t getLastKeyDownTimestamp() { return mLastKeyDownTimestamp; };
+
+private:
+ nsecs_t mLastKeyDownTimestamp;
};
template <class Fdp>
diff --git a/services/surfaceflinger/FlagManager.cpp b/services/surfaceflinger/FlagManager.cpp
index a8f05bb..1f8a3f5 100644
--- a/services/surfaceflinger/FlagManager.cpp
+++ b/services/surfaceflinger/FlagManager.cpp
@@ -102,6 +102,9 @@
DUMP_FLAG(misc1);
DUMP_FLAG(late_boot_misc2);
DUMP_FLAG(vrr_config);
+ DUMP_FLAG(hotplug2);
+ DUMP_FLAG(hdcp_level_hal);
+ DUMP_FLAG(multithreaded_present);
#undef DUMP_FLAG
}
@@ -165,6 +168,9 @@
FLAG_MANAGER_READ_ONLY_FLAG(enable_small_area_detection, "")
FLAG_MANAGER_READ_ONLY_FLAG(misc1, "")
FLAG_MANAGER_READ_ONLY_FLAG(vrr_config, "debug.sf.enable_vrr_config")
+FLAG_MANAGER_READ_ONLY_FLAG(hotplug2, "")
+FLAG_MANAGER_READ_ONLY_FLAG(hdcp_level_hal, "")
+FLAG_MANAGER_READ_ONLY_FLAG(multithreaded_present, "debug.sf.multithreaded_present")
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(late_boot_misc2, "")
diff --git a/services/surfaceflinger/FlagManager.h b/services/surfaceflinger/FlagManager.h
index 5a353bb..10784a7 100644
--- a/services/surfaceflinger/FlagManager.h
+++ b/services/surfaceflinger/FlagManager.h
@@ -51,6 +51,9 @@
bool enable_small_area_detection() const;
bool misc1() const;
bool vrr_config() const;
+ bool hotplug2() const;
+ bool hdcp_level_hal() const;
+ bool multithreaded_present() const;
/// Trunk stable server flags ///
bool late_boot_misc2() const;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index 7a85da0..38974a2 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -332,6 +332,14 @@
return geomBufferSize.toFloatRect();
}
+bool LayerSnapshot::isFrontBuffered() const {
+ if (!externalTexture) {
+ return false;
+ }
+
+ return externalTexture->getUsage() & AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
+}
+
Hwc2::IComposerClient::BlendMode LayerSnapshot::getBlendMode(
const RequestedLayerState& requested) const {
auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 4fd6495..73ee22f 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -143,6 +143,7 @@
std::string getIsVisibleReason() const;
bool hasInputInfo() const;
FloatRect sourceBounds() const;
+ bool isFrontBuffered() const;
Hwc2::IComposerClient::BlendMode getBlendMode(const RequestedLayerState& requested) const;
friend std::ostream& operator<<(std::ostream& os, const LayerSnapshot& obj);
void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 700baa2..66ea15c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -4024,10 +4024,10 @@
return getAlpha() > 0.0f || hasBlur();
}
-void Layer::onPostComposition(const DisplayDevice* display,
- const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) {
+void Layer::onCompositionPresented(const DisplayDevice* display,
+ const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) {
// mFrameLatencyNeeded is true when a new frame was latched for the
// composition.
if (!mBufferInfo.mFrameLatencyNeeded) return;
@@ -4230,6 +4230,14 @@
return hasBufferOrSidebandStream() ? mBufferInfo.mDataspace : mDrawingState.dataspace;
}
+bool Layer::isFrontBuffered() const {
+ if (mBufferInfo.mBuffer == nullptr) {
+ return false;
+ }
+
+ return mBufferInfo.mBuffer->getUsage() & AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
+}
+
ui::Dataspace Layer::translateDataspace(ui::Dataspace dataspace) {
ui::Dataspace updatedDataspace = dataspace;
// translate legacy dataspaces to modern dataspaces
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index dd91adc..f715910 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -342,6 +342,8 @@
//
ui::Dataspace getDataSpace() const;
+ virtual bool isFrontBuffered() const;
+
virtual sp<LayerFE> getCompositionEngineLayerFE() const;
virtual sp<LayerFE> copyCompositionEngineLayerFE() const;
sp<LayerFE> getCompositionEngineLayerFE(const frontend::LayerHierarchy::TraversalPath&);
@@ -433,13 +435,10 @@
void updateCloneBufferInfo();
uint64_t mPreviousFrameNumber = 0;
- /*
- * called after composition.
- * returns true if the layer latched a new buffer this frame.
- */
- void onPostComposition(const DisplayDevice*, const std::shared_ptr<FenceTime>& /*glDoneFence*/,
- const std::shared_ptr<FenceTime>& /*presentFence*/,
- const CompositorTiming&);
+ void onCompositionPresented(const DisplayDevice*,
+ const std::shared_ptr<FenceTime>& /*glDoneFence*/,
+ const std::shared_ptr<FenceTime>& /*presentFence*/,
+ const CompositorTiming&);
// If a buffer was replaced this frame, release the former buffer
void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/);
@@ -915,14 +914,13 @@
void recordLayerHistoryBufferUpdate(const scheduler::LayerProps&, nsecs_t now);
void recordLayerHistoryAnimationTx(const scheduler::LayerProps&, nsecs_t now);
auto getLayerProps() const {
- return scheduler::LayerProps{
- .visible = isVisible(),
- .bounds = getBounds(),
- .transform = getTransform(),
- .setFrameRateVote = getFrameRateForLayerTree(),
- .frameRateSelectionPriority = getFrameRateSelectionPriority(),
- .isSmallDirty = mSmallDirty,
- };
+ return scheduler::LayerProps{.visible = isVisible(),
+ .bounds = getBounds(),
+ .transform = getTransform(),
+ .setFrameRateVote = getFrameRateForLayerTree(),
+ .frameRateSelectionPriority = getFrameRateSelectionPriority(),
+ .isSmallDirty = mSmallDirty,
+ .isFrontBuffered = isFrontBuffered()};
};
bool hasBuffer() const { return mBufferInfo.mBuffer != nullptr; }
void setTransformHint(std::optional<ui::Transform::RotationFlags> transformHint) {
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 21bbb08..8fc9cba 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -51,6 +51,11 @@
return true;
}
+ // Make all front buffered layers active
+ if (FlagManager::getInstance().vrr_config() && info.isFrontBuffered() && info.isVisible()) {
+ return true;
+ }
+
return info.isVisible() && info.getLastUpdatedTime() >= threshold;
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 54e9022..8d18769 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -334,6 +334,14 @@
return votes;
}
+ // Vote for max refresh rate whenever we're front-buffered.
+ if (FlagManager::getInstance().vrr_config() && isFrontBuffered()) {
+ ATRACE_FORMAT_INSTANT("front buffered");
+ ALOGV("%s is front-buffered", mName.c_str());
+ votes.push_back({LayerHistory::LayerVoteType::Max, Fps()});
+ return votes;
+ }
+
const LayerInfo::Frequent frequent = isFrequent(now);
mIsFrequencyConclusive = frequent.isConclusive;
if (!frequent.isFrequent) {
@@ -394,6 +402,10 @@
return mLayerProps->frameRateSelectionPriority;
}
+bool LayerInfo::isFrontBuffered() const {
+ return mLayerProps->isFrontBuffered;
+}
+
FloatRect LayerInfo::getBounds() const {
return mLayerProps->bounds;
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 7d3cffa..03ab0df 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -200,6 +200,7 @@
FrameRate getSetFrameRateVote() const;
bool isVisible() const;
int32_t getFrameRateSelectionPriority() const;
+ bool isFrontBuffered() const;
FloatRect getBounds() const;
ui::Transform getTransform() const;
@@ -360,6 +361,7 @@
LayerInfo::FrameRate setFrameRateVote;
int32_t frameRateSelectionPriority = -1;
bool isSmallDirty = false;
+ bool isFrontBuffered = false;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index d3db523..56a4ae2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -1178,7 +1178,7 @@
}
}
-bool Scheduler::onPostComposition(nsecs_t presentTime) {
+bool Scheduler::onCompositionPresented(nsecs_t presentTime) {
std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index a5a5e8d..a02180a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -282,8 +282,8 @@
// Notifies the scheduler about a refresh rate timeline change.
void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline);
- // Notifies the scheduler post composition. Returns if recomposite is needed.
- bool onPostComposition(nsecs_t presentTime);
+ // Notifies the scheduler once the composition is presented. Returns if recomposite is needed.
+ bool onCompositionPresented(nsecs_t presentTime);
// Notifies the scheduler when the display size has changed. Called from SF's main thread
void onActiveDisplayAreaChanged(uint32_t displayArea);
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index 186a6bc..3e7ec49 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -38,19 +38,16 @@
namespace {
-nsecs_t getExpectedCallbackTime(nsecs_t now, nsecs_t nextVsyncTime,
+nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
const VSyncDispatch::ScheduleTiming& timing) {
- const auto expectedCallbackTime = nextVsyncTime - timing.readyDuration - timing.workDuration;
- const auto baseTime =
- FlagManager::getInstance().dont_skip_on_early() ? now : expectedCallbackTime;
- return std::max(baseTime, expectedCallbackTime);
+ return nextVsyncTime - timing.readyDuration - timing.workDuration;
}
nsecs_t getExpectedCallbackTime(VSyncTracker& tracker, nsecs_t now,
const VSyncDispatch::ScheduleTiming& timing) {
const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
- return getExpectedCallbackTime(now, nextVsyncTime, timing);
+ return getExpectedCallbackTime(nextVsyncTime, timing);
}
} // namespace
@@ -106,21 +103,23 @@
mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
if (FlagManager::getInstance().dont_skip_on_early()) {
if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
- return getExpectedCallbackTime(now, mArmedInfo->mActualVsyncTime, timing);
+ nextVsyncTime = mArmedInfo->mActualVsyncTime;
+ } else {
+ nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
}
+ nextWakeupTime = std::max(now, nextVsyncTime - timing.workDuration - timing.readyDuration);
} else {
if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
- return getExpectedCallbackTime(now, nextVsyncTime, timing);
+ return getExpectedCallbackTime(nextVsyncTime, timing);
}
+ nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
+ nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
}
- nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
- nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
-
auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
mScheduleTiming = timing;
mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
- return getExpectedCallbackTime(now, nextVsyncTime, timing);
+ return nextWakeupTime;
}
void VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming timing) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b1d8db5..15cae33 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2247,6 +2247,7 @@
.setFrameRateVote = snapshot->frameRate,
.frameRateSelectionPriority = snapshot->frameRateSelectionPriority,
.isSmallDirty = snapshot->isSmallDirty,
+ .isFrontBuffered = snapshot->isFrontBuffered(),
};
if (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) {
@@ -2747,11 +2748,11 @@
mPowerAdvisor->reportActualWorkDuration();
}
- if (mScheduler->onPostComposition(presentTime)) {
+ if (mScheduler->onCompositionPresented(presentTime)) {
scheduleComposite(FrameHint::kNone);
}
- postComposition(pacesetterId, frameTargeters, presentTime);
+ onCompositionPresented(pacesetterId, frameTargeters, presentTime);
const bool hadGpuComposited =
multiDisplayUnion(mCompositionCoverage).test(CompositionCoverage::Gpu);
@@ -2908,9 +2909,9 @@
return ui::ROTATION_0;
}
-void SurfaceFlinger::postComposition(PhysicalDisplayId pacesetterId,
- const scheduler::FrameTargeters& frameTargeters,
- nsecs_t presentStartTime) {
+void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId,
+ const scheduler::FrameTargeters& frameTargeters,
+ nsecs_t presentStartTime) {
ATRACE_CALL();
ALOGV(__func__);
@@ -3004,8 +3005,9 @@
mLayersWithBuffersRemoved.clear();
for (const auto& layer: mLayersWithQueuedFrames) {
- layer->onPostComposition(pacesetterDisplay.get(), pacesetterGpuCompositionDoneFenceTime,
- pacesetterPresentFenceTime, compositorTiming);
+ layer->onCompositionPresented(pacesetterDisplay.get(),
+ pacesetterGpuCompositionDoneFenceTime,
+ pacesetterPresentFenceTime, compositorTiming);
layer->releasePendingBuffer(presentTime.ns());
}
@@ -4899,6 +4901,7 @@
.transform = layer->getTransform(),
.setFrameRateVote = layer->getFrameRateForLayerTree(),
.frameRateSelectionPriority = layer->getFrameRateSelectionPriority(),
+ .isFrontBuffered = layer->isFrontBuffered(),
};
layer->recordLayerHistoryAnimationTx(layerProps, now);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 94eedc8..1e90340 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -987,8 +987,8 @@
/*
* Compositing
*/
- void postComposition(PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters&,
- nsecs_t presentStartTime) REQUIRES(kMainThreadContext);
+ void onCompositionPresented(PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters&,
+ nsecs_t presentStartTime) REQUIRES(kMainThreadContext);
/*
* Display management
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 70ce884..9b2d453 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -614,8 +614,8 @@
mFlinger->flushTransactionQueues(getFuzzedVsyncId(mFdp));
scheduler::FrameTargeter frameTargeter(displayId, mFdp.ConsumeBool());
- mFlinger->postComposition(displayId, ftl::init::map(displayId, &frameTargeter),
- mFdp.ConsumeIntegral<nsecs_t>());
+ mFlinger->onCompositionPresented(displayId, ftl::init::map(displayId, &frameTargeter),
+ mFdp.ConsumeIntegral<nsecs_t>());
}
mFlinger->setTransactionFlags(mFdp.ConsumeIntegral<uint32_t>());
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
index 39a7ee5..7aae3c4 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
@@ -133,7 +133,7 @@
ui::LayerStack::fromValue(mFdp.ConsumeIntegral<uint32_t>()));
layer->releasePendingBuffer(mFdp.ConsumeIntegral<int64_t>());
- layer->onPostComposition(nullptr, fenceTime, fenceTime, compositorTiming);
+ layer->onCompositionPresented(nullptr, fenceTime, fenceTime, compositorTiming);
layer->setTransform(mFdp.ConsumeIntegral<uint32_t>());
layer->setTransformToDisplayInverse(mFdp.ConsumeBool());
diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig
index 19d194f..a81f9b8 100644
--- a/services/surfaceflinger/surfaceflinger_flags.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -52,4 +52,21 @@
description: "Feature flag for SmallAreaDetection"
bug: "283055450"
is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+ name: "hotplug2"
+ namespace: "core_graphics"
+ description: "Feature flag for using hotplug2 HAL API"
+ bug: "303460805"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "hdcp_level_hal"
+ namespace: "core_graphics"
+ description: "Feature flag for adding a HAL API to commuicate hdcp levels"
+ bug: "285359126"
+ is_fixed_read_only: true
+}
+
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 5328fa3..1adf14f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -927,6 +927,43 @@
EXPECT_EQ(1, animatingLayerCount(time));
}
+TEST_F(LayerHistoryTest, frontBufferedLayerVotesMax) {
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ auto layer = createLayer();
+
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+ EXPECT_CALL(*layer, isFrontBuffered()).WillRepeatedly(Return(true));
+
+ nsecs_t time = systemTime();
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+
+ // layer is active but infrequent.
+ for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+ LayerHistory::LayerUpdateType::Buffer);
+ time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
+ }
+
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(1, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+
+ // layer became inactive
+ time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(1, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+}
+
TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
auto layer = createLayer();
diff --git a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
index 830dcce..047ef5a 100644
--- a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
@@ -21,6 +21,7 @@
#include <scheduler/Fps.h>
+#include "FlagUtils.h"
#include "FpsOps.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/LayerInfo.h"
@@ -28,6 +29,8 @@
#include "TestableSurfaceFlinger.h"
#include "mock/MockSchedulerCallback.h"
+#include <com_android_graphics_surfaceflinger_flags.h>
+
namespace android::scheduler {
using android::mock::createDisplayMode;
@@ -69,6 +72,8 @@
namespace {
+using namespace com::android::graphics::surfaceflinger;
+
TEST_F(LayerInfoTest, prefersPresentTime) {
std::deque<FrameTimeData> frameTimes;
constexpr auto kExpectedFps = 50_Hz;
@@ -263,5 +268,18 @@
ASSERT_EQ(actualVotes[0].fps, vote.fps);
}
+TEST_F(LayerInfoTest, isFrontBuffered) {
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ ASSERT_FALSE(layerInfo.isFrontBuffered());
+
+ LayerProps prop = {.isFrontBuffered = true};
+ layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop);
+ ASSERT_TRUE(layerInfo.isFrontBuffered());
+
+ prop.isFrontBuffered = false;
+ layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop);
+ ASSERT_FALSE(layerInfo.isFrontBuffered());
+}
+
} // namespace
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index e784eb7..57babaf 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -898,4 +898,24 @@
gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
}
+TEST_F(LayerSnapshotTest, isFrontBuffered) {
+ setBuffer(1,
+ std::make_shared<renderengine::mock::FakeExternalTexture>(
+ 1U /*width*/, 1U /*height*/, 1ULL /* bufferId */, HAL_PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_HW_TEXTURE | AHARDWAREBUFFER_USAGE_FRONT_BUFFER /*usage*/));
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot(1)->isFrontBuffered());
+
+ setBuffer(1,
+ std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_HW_TEXTURE /*usage*/));
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_FALSE(getSnapshot(1)->isFrontBuffered());
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index 00b5bf0..d4d5b32 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -112,7 +112,7 @@
EXPECT_CALL(*mFlinger.getFrameTracer(),
traceFence(layerId, bufferId, frameNumber, presentFence,
FrameTracer::FrameEvent::PRESENT_FENCE, /*startTime*/ 0));
- layer->onPostComposition(nullptr, glDoneFence, presentFence, compositorTiming);
+ layer->onCompositionPresented(nullptr, glDoneFence, presentFence, compositorTiming);
}
};
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index fbbb4a2..8310866 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -783,7 +783,9 @@
TEST_F(VSyncDispatchTimerQueueTest, movesCallbackBackwardsAndSkipAScheduledTargetVSync) {
SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true);
- EXPECT_CALL(mMockClock, alarmAt(_, 500));
+ Sequence seq;
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 400)).InSequence(seq);
CountingCallback cb(mDispatch);
auto result =
mDispatch->schedule(cb,
@@ -873,7 +875,9 @@
TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesAffectSchedulingState) {
SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true);
- EXPECT_CALL(mMockClock, alarmAt(_, 600));
+ Sequence seq;
+ EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 0)).InSequence(seq);
CountingCallback cb(mDispatch);
auto result =
@@ -1119,6 +1123,7 @@
Sequence seq;
EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 0)).InSequence(seq);
CountingCallback cb(mDispatch);
@@ -1132,7 +1137,7 @@
ASSERT_THAT(cb.mCalls.size(), Eq(1));
EXPECT_THAT(cb.mCalls[0], Eq(1000));
ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
- EXPECT_THAT(cb.mWakeupTime[0], Eq(600));
+ EXPECT_THAT(cb.mWakeupTime[0], Eq(0));
ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
EXPECT_THAT(cb.mReadyTime[0], Eq(1000));
}
@@ -1161,7 +1166,9 @@
TEST_F(VSyncDispatchTimerQueueTest, dontskipAVsyc) {
SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true);
- EXPECT_CALL(mMockClock, alarmAt(_, 500));
+ Sequence seq;
+ EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
+ EXPECT_CALL(mMockClock, alarmAt(_, 300)).InSequence(seq);
CountingCallback cb(mDispatch);
auto result =
mDispatch->schedule(cb,
@@ -1177,6 +1184,11 @@
advanceToNextCallback();
ASSERT_THAT(cb.mCalls.size(), Eq(1));
+ EXPECT_THAT(cb.mCalls[0], Eq(1000));
+ ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
+ EXPECT_THAT(cb.mWakeupTime[0], Eq(300));
+ ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
+ EXPECT_THAT(cb.mReadyTime[0], Eq(1000));
}
class VSyncDispatchTimerQueueEntryTest : public testing::Test {
diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
index 4cc78fe..3dfb649 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
@@ -37,6 +37,7 @@
MOCK_CONST_METHOD0(getDefaultFrameRateCompatibility, scheduler::FrameRateCompatibility());
MOCK_CONST_METHOD0(getOwnerUid, uid_t());
MOCK_CONST_METHOD0(getDataSpace, ui::Dataspace());
+ MOCK_METHOD(bool, isFrontBuffered, (), (const, override));
};
} // namespace android::mock