Merge "GpuMemTracer: remove the sleep workaround"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index fc3572c..08f44c8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -172,6 +172,8 @@
{ OPT, "events/clk/clk_enable/enable" },
{ OPT, "events/power/cpu_frequency_limits/enable" },
{ OPT, "events/power/suspend_resume/enable" },
+ { OPT, "events/cpuhp/cpuhp_enter/enable" },
+ { OPT, "events/cpuhp/cpuhp_exit/enable" },
} },
{ "membus", "Memory Bus Utilization", 0, {
{ REQ, "events/memory_bus/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d2ccef1..994375b 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -47,6 +47,10 @@
chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_enter/enable
+ chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_enter/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit/enable
+ chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_exit/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/enable
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
index 8b03cfd..839a2c3 100644
--- a/cmds/dumpstate/TEST_MAPPING
+++ b/cmds/dumpstate/TEST_MAPPING
@@ -1,6 +1,13 @@
{
"presubmit": [
- // TODO(159590499) add BugreportManagerTestCases
+ {
+ "name": "BugreportManagerTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
+ },
{
"name": "dumpstate_smoke_test"
},
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 581d3de..8879aed 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -78,6 +78,7 @@
#include <hardware_legacy/power.h>
#include <hidl/ServiceManagement.h>
#include <log/log.h>
+#include <log/log_read.h>
#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -661,14 +662,24 @@
static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
-/* timeout in ms to read a list of buffers */
+// Returns the actual readable size of the given buffer or -1 on error.
+static long logcat_buffer_readable_size(const std::string& buffer) {
+ std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
+ android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
+ auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
+
+ return android_logger_get_log_readable_size(logger);
+}
+
+// Returns timeout in ms to read a list of buffers.
static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
unsigned long timeout_ms = 0;
for (const auto& buffer : buffers) {
- log_id_t id = android_name_to_log_id(buffer.c_str());
- unsigned long property_size = __android_logger_get_buffer_size(id);
- /* Engineering margin is ten-fold our guess */
- timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
+ long readable_size = logcat_buffer_readable_size(buffer);
+ if (readable_size > 0) {
+ // Engineering margin is ten-fold our guess.
+ timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
+ }
}
return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
}
@@ -1481,8 +1492,7 @@
RunCommand("LSMOD", {"lsmod"});
}
- if (__android_logger_property_get_bool(
- "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
+ if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
DoKernelLogcat();
} else {
do_dmesg();
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index 9a21104..fc745d0 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -1,6 +1,5 @@
set noparent
-agampe@google.com
calin@google.com
jsharkey@android.com
maco@google.com
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 18f8268..9c75781 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -96,7 +96,7 @@
template<typename T>
static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
- return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
+ return (x & -n);
}
template<typename T>
@@ -523,6 +523,7 @@
// Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
constexpr size_t kPageSize = PAGE_SIZE;
+ static_assert(IsPowerOfTwo(kPageSize), "page size must be power of two");
CHECK_EQ(min_delta % kPageSize, 0u);
CHECK_EQ(max_delta % kPageSize, 0u);
CHECK_LT(min_delta, max_delta);
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
new file mode 100644
index 0000000..83b6aa0
--- /dev/null
+++ b/data/etc/Android.bp
@@ -0,0 +1,7 @@
+prebuilt_etc {
+ name: "android.hardware.biometrics.face.xml",
+ product_specific: true,
+ sub_dir: "permissions",
+ src: "android.hardware.biometrics.face.xml",
+ filename_from_src: true,
+}
\ No newline at end of file
diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h
index b6b9353..8e4fe79 100644
--- a/include/input/InputApplication.h
+++ b/include/input/InputApplication.h
@@ -19,6 +19,8 @@
#include <string>
+#include <android/InputApplicationInfo.h>
+
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
@@ -28,29 +30,13 @@
#include <utils/Timers.h>
namespace android {
-
-/*
- * Describes the properties of an application that can receive input.
- */
-struct InputApplicationInfo : public Parcelable {
- sp<IBinder> token;
- std::string name;
- std::chrono::nanoseconds dispatchingTimeout;
-
- InputApplicationInfo() = default;
-
- status_t readFromParcel(const android::Parcel* parcel) override;
-
- status_t writeToParcel(android::Parcel* parcel) const override;
-};
-
/*
* Handle for an application that can receive input.
*
* Used by the native input dispatcher as a handle for the window manager objects
* that describe an application.
*/
-class InputApplicationHandle : public RefBase {
+class InputApplicationHandle {
public:
inline const InputApplicationInfo* getInfo() const {
return &mInfo;
@@ -62,13 +48,20 @@
inline std::chrono::nanoseconds getDispatchingTimeout(
std::chrono::nanoseconds defaultValue) const {
- return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue;
+ return mInfo.token ? std::chrono::milliseconds(mInfo.dispatchingTimeoutMillis)
+ : defaultValue;
}
inline sp<IBinder> getApplicationToken() const {
return mInfo.token;
}
+ bool operator==(const InputApplicationHandle& other) const {
+ return getName() == other.getName() && getApplicationToken() == other.getApplicationToken();
+ }
+
+ bool operator!=(const InputApplicationHandle& other) const { return !(*this == other); }
+
/**
* Requests that the state of this object be updated to reflect
* the most current available information about the application.
@@ -81,8 +74,8 @@
virtual bool updateInfo() = 0;
protected:
- InputApplicationHandle();
- virtual ~InputApplicationHandle();
+ InputApplicationHandle() = default;
+ virtual ~InputApplicationHandle() = default;
InputApplicationInfo mInfo;
};
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index b24a577..861b589 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -127,6 +127,10 @@
export_aidl_headers: true,
},
+ // TODO(b/142684679): for com.android.media which is compiled
+ // as vendor and used as system code.
+ use_apex_name_macro: true,
+
cflags: [
"-Wall",
"-Wextra",
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 1c6b491..de42f36 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -22,6 +22,7 @@
#include <utils/SystemClock.h>
#include <sys/types.h>
+#include <private/android_filesystem_config.h>
#ifdef LOG_TAG
#undef LOG_TAG
@@ -100,7 +101,7 @@
sp<IAppOpsService> service = getService();
int32_t mode = service != nullptr
? service->noteOperation(op, uid, callingPackage, attributionTag,
- shouldCollectNotes(op), message)
+ shouldCollectNotes(op), message, uid == AID_SYSTEM)
: AppOpsManager::MODE_IGNORED;
return mode;
@@ -118,7 +119,8 @@
sp<IAppOpsService> service = getService();
int32_t mode = service != nullptr
? service->startOperation(getClientId(), op, uid, callingPackage,
- attributionTag, startIfModeDefault, shouldCollectNotes(op), message)
+ attributionTag, startIfModeDefault, shouldCollectNotes(op), message,
+ uid == AID_SYSTEM)
: AppOpsManager::MODE_IGNORED;
return mode;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index d2b9b8f..c183d29 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -224,7 +224,7 @@
using android::internal::Stability;
auto stability = Stability::get(this);
- auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
+ auto required = privateVendor ? Stability::VENDOR : Stability::getLocalStability();
if (CC_UNLIKELY(!Stability::check(stability, required))) {
ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index cd78866..ee0cd62 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -50,15 +50,16 @@
virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
const std::optional<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
- const String16& message) {
+ 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.writeInt32(shouldCollectAsyncNotedOp ? 1 : 0);
+ data.writeBool(shouldCollectAsyncNotedOp);
data.writeString16(message);
+ data.writeBool(shouldCollectMessage);
remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
@@ -67,7 +68,8 @@
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 startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message,
+ bool shouldCollectMessage) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(token);
@@ -75,9 +77,10 @@
data.writeInt32(uid);
data.writeString16(packageName);
data.writeString16(attributionTag);
- data.writeInt32(startIfModeDefault ? 1 : 0);
- data.writeInt32(shouldCollectAsyncNotedOp ? 1 : 0);
+ data.writeBool(startIfModeDefault);
+ data.writeBool(shouldCollectAsyncNotedOp);
data.writeString16(message);
+ data.writeBool(shouldCollectMessage);
remote()->transact(START_OPERATION_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
@@ -186,10 +189,11 @@
String16 packageName = data.readString16();
std::optional<String16> attributionTag;
data.readString16(&attributionTag);
- bool shouldCollectAsyncNotedOp = data.readInt32() == 1;
+ bool shouldCollectAsyncNotedOp = data.readBool();
String16 message = data.readString16();
+ bool shouldCollectMessage = data.readBool();
int32_t res = noteOperation(code, uid, packageName, attributionTag,
- shouldCollectAsyncNotedOp, message);
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
@@ -202,11 +206,12 @@
String16 packageName = data.readString16();
std::optional<String16> attributionTag;
data.readString16(&attributionTag);
- bool startIfModeDefault = data.readInt32() == 1;
- bool shouldCollectAsyncNotedOp = data.readInt32() == 1;
+ 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,
- startIfModeDefault, shouldCollectAsyncNotedOp, message);
+ startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d67ce15..157538e 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -614,7 +614,7 @@
talkWithDriver(false);
}
-int IPCThreadState::setupPolling(int* fd)
+status_t IPCThreadState::setupPolling(int* fd)
{
if (mProcess->mDriverFD < 0) {
return -EBADF;
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index e1565fa..6115aec 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -22,7 +22,7 @@
namespace internal {
void Stability::markCompilationUnit(IBinder* binder) {
- status_t result = set(binder, kLocalStability, true /*log*/);
+ status_t result = set(binder, getLocalStability(), true /*log*/);
LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
}
@@ -45,7 +45,26 @@
}
void Stability::tryMarkCompilationUnit(IBinder* binder) {
- (void) set(binder, kLocalStability, false /*log*/);
+ (void) set(binder, getLocalStability(), false /*log*/);
+}
+
+Stability::Level Stability::getLocalStability() {
+#ifdef __ANDROID_VNDK__
+ #ifdef __ANDROID_APEX__
+ // TODO(b/142684679) avoid use_vendor on system APEXes
+ #if !defined(__ANDROID_APEX_COM_ANDROID_MEDIA_SWCODEC__) \
+ && !defined(__ANDROID_APEX_TEST_COM_ANDROID_MEDIA_SWCODEC__)
+ #error VNDK + APEX only defined for com.android.media.swcodec
+ #endif
+ // TODO(b/142684679) avoid use_vendor on system APEXes
+ return Level::SYSTEM;
+ #else
+ return Level::VENDOR;
+ #endif
+#else
+ // TODO(b/139325195): split up stability levels for system/APEX.
+ return Level::SYSTEM;
+#endif
}
status_t Stability::set(IBinder* binder, int32_t stability, bool log) {
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index a4a20c8..de7d12f 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -39,10 +39,11 @@
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,
- const String16& message) = 0;
+ 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) = 0;
+ 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 void startWatchingMode(int32_t op, const String16& packageName,
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 8d51cdc..2bd39a7 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -85,8 +85,8 @@
int64_t clearCallingIdentity();
// Restores PID/UID (not SID)
void restoreCallingIdentity(int64_t token);
-
- int setupPolling(int* fd);
+
+ status_t setupPolling(int* fd);
status_t handlePolledCommands();
void flushCommands();
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index 6d711bc..d18c88e 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -26,7 +26,19 @@
class ClientCounterCallback;
} // namespace internal
-/** Exits when all services registered through this object have 0 clients */
+/**
+ * Exits when all services registered through this object have 0 clients
+ *
+ * In order to use this class, it's expected that your service:
+ * - registers all services in the process with this API
+ * - configures services as oneshot in init .rc files
+ * - configures services as disabled in init.rc files, unless a client is
+ * guaranteed early in boot, in which case, forcePersist should also be used
+ * to avoid races.
+ * - uses 'interface' declarations in init .rc files
+ *
+ * For more information on init .rc configuration, see system/core/init/README.md
+ **/
class LazyServiceRegistrar {
public:
static LazyServiceRegistrar& getInstance();
@@ -47,4 +59,4 @@
};
} // namespace binder
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 2894482..6566285 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -81,11 +81,8 @@
VINTF = 0b111111,
};
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
- static constexpr Level kLocalStability = Level::VENDOR;
-#else
- static constexpr Level kLocalStability = Level::SYSTEM;
-#endif
+ // returns the stability according to how this was built
+ static Level getLocalStability();
// applies stability to binder if stability level is known
__attribute__((warn_unused_result))
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 2b61cf1..f59bb75 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -189,6 +189,7 @@
explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {}
~ScopedAParcel() {}
ScopedAParcel(ScopedAParcel&&) = default;
+ ScopedAParcel& operator=(ScopedAParcel&&) = default;
};
/**
@@ -273,6 +274,7 @@
: ScopedAResource(a) {}
~ScopedAIBinder_DeathRecipient() {}
ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
+ ScopedAIBinder_DeathRecipient& operator=(ScopedAIBinder_DeathRecipient&&) = default;
};
/**
@@ -287,6 +289,7 @@
explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {}
~ScopedAIBinder_Weak() {}
ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default;
+ ScopedAIBinder_Weak& operator=(ScopedAIBinder_Weak&&) = default;
/**
* See AIBinder_Weak_promote.
@@ -305,6 +308,7 @@
explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {}
~ScopedFileDescriptor() {}
ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
+ ScopedFileDescriptor& operator=(ScopedFileDescriptor&&) = default;
};
} // namespace ndk
diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
index fdefbb4..f408fad 100644
--- a/libs/binder/ndk/include_platform/android/binder_process.h
+++ b/libs/binder/ndk/include_platform/android/binder_process.h
@@ -19,10 +19,15 @@
#include <stdint.h>
#include <sys/cdefs.h>
+#include <android/binder_status.h>
+
__BEGIN_DECLS
/**
* This creates a threadpool for incoming binder transactions if it has not already been created.
+ *
+ * When using this, it is expected that ABinderProcess_setupPolling and
+ * ABinderProcess_handlePolledCommands are not used.
*/
void ABinderProcess_startThreadPool();
/**
@@ -37,4 +42,27 @@
*/
void ABinderProcess_joinThreadPool();
+/**
+ * This gives you an fd to wait on. Whenever data is available on the fd,
+ * ABinderProcess_handlePolledCommands can be called to handle binder queries.
+ * This is expected to be used in a single threaded process which waits on
+ * events from multiple different fds.
+ *
+ * When using this, it is expected ABinderProcess_startThreadPool and
+ * ABinderProcess_joinThreadPool are not used.
+ *
+ * \param fd out param corresponding to the binder domain opened in this
+ * process.
+ * \return STATUS_OK on success
+ */
+__attribute__((weak)) binder_status_t ABinderProcess_setupPolling(int* fd) __INTRODUCED_IN(31);
+
+/**
+ * This will handle all queued binder commands in this process and then return.
+ * It is expected to be called whenever there is data on the fd.
+ *
+ * \return STATUS_OK on success
+ */
+__attribute__((weak)) binder_status_t ABinderProcess_handlePolledCommands() __INTRODUCED_IN(31);
+
__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 9b5fa26..d435382 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -113,6 +113,8 @@
LIBBINDER_NDK31 { # introduced=31
global:
+ ABinderProcess_handlePolledCommands; # apex
+ ABinderProcess_setupPolling; # apex
AIBinder_getCallingSid; # apex
AIBinder_setRequestingSid; # apex
};
diff --git a/libs/binder/ndk/process.cpp b/libs/binder/ndk/process.cpp
index c89caaf..ac582a4 100644
--- a/libs/binder/ndk/process.cpp
+++ b/libs/binder/ndk/process.cpp
@@ -34,3 +34,11 @@
void ABinderProcess_joinThreadPool() {
IPCThreadState::self()->joinThreadPool();
}
+
+binder_status_t ABinderProcess_setupPolling(int* fd) {
+ return IPCThreadState::self()->setupPolling(fd);
+}
+
+binder_status_t ABinderProcess_handlePolledCommands() {
+ return IPCThreadState::self()->handlePolledCommands();
+}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index e3fdb4b..9b2fcf0 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -24,6 +24,7 @@
#include <android/binder_process.h>
#include <gtest/gtest.h>
#include <iface/iface.h>
+#include <utils/Looper.h>
// warning: this is assuming that libbinder_ndk is using the same copy
// of libbinder that we are.
@@ -107,19 +108,39 @@
}
};
-int manualService(const char* instance) {
- ABinderProcess_setThreadPoolMaxThreadCount(0);
-
+void manualService(const char* instance) {
// Strong reference to MyFoo kept by service manager.
binder_status_t status = (new MyFoo)->addService(instance);
if (status != STATUS_OK) {
LOG(FATAL) << "Could not register: " << status << " " << instance;
}
+}
+int manualPollingService(const char* instance) {
+ int fd;
+ CHECK(STATUS_OK == ABinderProcess_setupPolling(&fd));
+ manualService(instance);
+ class Handler : public LooperCallback {
+ int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override {
+ ABinderProcess_handlePolledCommands();
+ return 1; // Continue receiving callbacks.
+ }
+ };
+
+ sp<Looper> looper = Looper::prepare(0 /* opts */);
+ looper->addFd(fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, new Handler(), nullptr /*data*/);
+ // normally, would add additional fds
+ while (true) {
+ looper->pollAll(-1 /* timeoutMillis */);
+ }
+ return 1; // should not reach
+}
+int manualThreadPoolService(const char* instance) {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ manualService(instance);
ABinderProcess_joinThreadPool();
-
- return 1; // should not return
+ return 1;
}
// This is too slow
@@ -448,11 +469,11 @@
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
- return manualService(IFoo::kInstanceNameToDieFor);
+ return manualThreadPoolService(IFoo::kInstanceNameToDieFor);
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
- return manualService(IFoo::kSomeInstanceName);
+ return manualPollingService(IFoo::kSomeInstanceName);
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 489f3c3..1f71e23 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -696,7 +696,7 @@
// relationship, thus |getConsumerName| from the producer side does not
// make any sense.
ALOGE("BufferHubProducer::getConsumerName not supported.");
- return String8("BufferHubQueue::DummyConsumer");
+ return String8("BufferHubQueue::StubConsumer");
}
status_t BufferHubProducer::setSharedBufferMode(bool shared_buffer_mode) {
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index b33bc9e..51fbb97 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -121,9 +121,8 @@
PhysicalDisplayId vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
- ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
- ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d",
- this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);
+ ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d", this,
+ ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount);
mWaitingForVsync = false;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 59f1bcd..30d19e3 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -280,7 +280,7 @@
mCurrentFenceTime = FenceTime::NO_FENCE;
if (mAttached) {
- // This binds a dummy buffer (mReleasedTexImage).
+ // This binds a buffer placeholder (mReleasedTexImage).
status_t result = bindTextureImageLocked();
if (result != NO_ERROR) {
return result;
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 5c81b9d..0683087 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -119,7 +119,7 @@
return BBinder::onTransact(code, data, reply, flags);
}
-DummyProducerListener::~DummyProducerListener() = default;
+StubProducerListener::~StubProducerListener() = default;
bool BnProducerListener::needsReleaseNotify() {
return true;
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 6881be3..4a12035 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -111,81 +111,64 @@
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- bool& outCapturedSecureLayers, ui::Dataspace reqDataspace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, bool captureSecureLayers) {
+ virtual status_t captureDisplay(const DisplayCaptureArgs& args,
+ ScreenCaptureResults& captureResults) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- data.writeInt32(static_cast<int32_t>(reqDataspace));
- data.writeInt32(static_cast<int32_t>(reqPixelFormat));
- data.write(sourceCrop);
- data.writeUint32(reqWidth);
- data.writeUint32(reqHeight);
- data.writeInt32(static_cast<int32_t>(useIdentityTransform));
- data.writeInt32(static_cast<int32_t>(rotation));
- data.writeInt32(static_cast<int32_t>(captureSecureLayers));
- status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
+
+ status_t result = args.write(data);
if (result != NO_ERROR) {
- ALOGE("captureScreen failed to transact: %d", result);
+ ALOGE("captureDisplay failed to parcel args: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("captureDisplay failed to transact: %d", result);
return result;
}
result = reply.readInt32();
if (result != NO_ERROR) {
- ALOGE("captureScreen failed to readInt32: %d", result);
+ ALOGE("captureDisplay failed to readInt32: %d", result);
return result;
}
- *outBuffer = new GraphicBuffer();
- reply.read(**outBuffer);
- outCapturedSecureLayers = reply.readBool();
-
+ captureResults.read(reply);
return result;
}
- virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
- sp<GraphicBuffer>* outBuffer) {
+ virtual status_t captureDisplay(uint64_t displayOrLayerStack,
+ ScreenCaptureResults& captureResults) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeUint64(displayOrLayerStack);
- status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_BY_ID, data, &reply);
+ status_t result =
+ remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply);
if (result != NO_ERROR) {
- ALOGE("captureScreen failed to transact: %d", result);
+ ALOGE("captureDisplay failed to transact: %d", result);
return result;
}
result = reply.readInt32();
if (result != NO_ERROR) {
- ALOGE("captureScreen failed to readInt32: %d", result);
+ ALOGE("captureDisplay failed to readInt32: %d", result);
return result;
}
- *outDataspace = static_cast<ui::Dataspace>(reply.readInt32());
- *outBuffer = new GraphicBuffer();
- reply.read(**outBuffer);
+ captureResults.read(reply);
return result;
}
- virtual status_t captureLayers(
- const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
- const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
- const Rect& sourceCrop,
- const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& excludeLayers, float frameScale,
- bool childrenOnly) {
+ virtual status_t captureLayers(const LayerCaptureArgs& args,
+ ScreenCaptureResults& captureResults) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(layerHandleBinder);
- data.writeInt32(static_cast<int32_t>(reqDataspace));
- data.writeInt32(static_cast<int32_t>(reqPixelFormat));
- data.write(sourceCrop);
- data.writeInt32(excludeLayers.size());
- for (auto el : excludeLayers) {
- data.writeStrongBinder(el);
+
+ status_t result = args.write(data);
+ if (result != NO_ERROR) {
+ ALOGE("captureLayers failed to parcel args: %d", result);
+ return result;
}
- data.writeFloat(frameScale);
- data.writeBool(childrenOnly);
- status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
+
+ result = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
if (result != NO_ERROR) {
ALOGE("captureLayers failed to transact: %d", result);
return result;
@@ -196,9 +179,7 @@
return result;
}
- *outBuffer = new GraphicBuffer();
- reply.read(**outBuffer);
-
+ captureResults.read(reply);
return result;
}
@@ -327,8 +308,11 @@
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) ==
NO_ERROR) {
- std::vector<PhysicalDisplayId> displayIds;
- if (reply.readUint64Vector(&displayIds) == NO_ERROR) {
+ std::vector<uint64_t> rawIds;
+ if (reply.readUint64Vector(&rawIds) == NO_ERROR) {
+ std::vector<PhysicalDisplayId> displayIds(rawIds.size());
+ std::transform(rawIds.begin(), rawIds.end(), displayIds.begin(),
+ [](uint64_t rawId) { return PhysicalDisplayId(rawId); });
return displayIds;
}
}
@@ -339,7 +323,7 @@
virtual sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeUint64(displayId);
+ data.writeUint64(displayId.value);
remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_TOKEN, data, &reply);
return reply.readStrongBinder();
}
@@ -1293,74 +1277,51 @@
bootFinished();
return NO_ERROR;
}
- case CAPTURE_SCREEN: {
+ case CAPTURE_DISPLAY: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = data.readStrongBinder();
- ui::Dataspace reqDataspace = static_cast<ui::Dataspace>(data.readInt32());
- ui::PixelFormat reqPixelFormat = static_cast<ui::PixelFormat>(data.readInt32());
- sp<GraphicBuffer> outBuffer;
- Rect sourceCrop(Rect::EMPTY_RECT);
- data.read(sourceCrop);
- uint32_t reqWidth = data.readUint32();
- uint32_t reqHeight = data.readUint32();
- bool useIdentityTransform = static_cast<bool>(data.readInt32());
- int32_t rotation = data.readInt32();
- bool captureSecureLayers = static_cast<bool>(data.readInt32());
+ DisplayCaptureArgs args;
+ ScreenCaptureResults captureResults;
- bool capturedSecureLayers = false;
- status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, reqDataspace,
- reqPixelFormat, sourceCrop, reqWidth, reqHeight,
- useIdentityTransform, ui::toRotation(rotation),
- captureSecureLayers);
+ status_t res = args.read(data);
+ if (res != NO_ERROR) {
+ reply->writeInt32(res);
+ return NO_ERROR;
+ }
+
+ res = captureDisplay(args, captureResults);
reply->writeInt32(res);
if (res == NO_ERROR) {
- reply->write(*outBuffer);
- reply->writeBool(capturedSecureLayers);
+ captureResults.write(*reply);
}
return NO_ERROR;
}
- case CAPTURE_SCREEN_BY_ID: {
+ case CAPTURE_DISPLAY_BY_ID: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
uint64_t displayOrLayerStack = data.readUint64();
- ui::Dataspace outDataspace = ui::Dataspace::V0_SRGB;
- sp<GraphicBuffer> outBuffer;
- status_t res = captureScreen(displayOrLayerStack, &outDataspace, &outBuffer);
+ ScreenCaptureResults captureResults;
+ status_t res = captureDisplay(displayOrLayerStack, captureResults);
reply->writeInt32(res);
if (res == NO_ERROR) {
- reply->writeInt32(static_cast<int32_t>(outDataspace));
- reply->write(*outBuffer);
+ captureResults.write(*reply);
}
return NO_ERROR;
}
case CAPTURE_LAYERS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> layerHandleBinder = data.readStrongBinder();
- ui::Dataspace reqDataspace = static_cast<ui::Dataspace>(data.readInt32());
- ui::PixelFormat reqPixelFormat = static_cast<ui::PixelFormat>(data.readInt32());
- sp<GraphicBuffer> outBuffer;
- Rect sourceCrop(Rect::EMPTY_RECT);
- data.read(sourceCrop);
+ LayerCaptureArgs args;
+ ScreenCaptureResults captureResults;
- std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles;
- int numExcludeHandles = data.readInt32();
- if (numExcludeHandles >= static_cast<int>(MAX_LAYERS)) {
- return BAD_VALUE;
- }
- excludeHandles.reserve(numExcludeHandles);
- for (int i = 0; i < numExcludeHandles; i++) {
- excludeHandles.emplace(data.readStrongBinder());
+ status_t res = args.read(data);
+ if (res != NO_ERROR) {
+ reply->writeInt32(res);
+ return NO_ERROR;
}
- float frameScale = data.readFloat();
- bool childrenOnly = data.readBool();
-
- status_t res =
- captureLayers(layerHandleBinder, &outBuffer, reqDataspace, reqPixelFormat,
- sourceCrop, excludeHandles, frameScale, childrenOnly);
+ res = captureLayers(args, captureResults);
reply->writeInt32(res);
if (res == NO_ERROR) {
- reply->write(*outBuffer);
+ captureResults.write(*reply);
}
return NO_ERROR;
}
@@ -1417,7 +1378,7 @@
}
case GET_PHYSICAL_DISPLAY_TOKEN: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- PhysicalDisplayId displayId = data.readUint64();
+ PhysicalDisplayId displayId(data.readUint64());
sp<IBinder> display = getPhysicalDisplayToken(displayId);
reply->writeStrongBinder(display);
return NO_ERROR;
@@ -1819,7 +1780,11 @@
}
case GET_PHYSICAL_DISPLAY_IDS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- return reply->writeUint64Vector(getPhysicalDisplayIds());
+ std::vector<PhysicalDisplayId> ids = getPhysicalDisplayIds();
+ std::vector<uint64_t> rawIds(ids.size());
+ std::transform(ids.begin(), ids.end(), rawIds.begin(),
+ [](PhysicalDisplayId id) { return id.value; });
+ return reply->writeUint64Vector(rawIds);
}
case ADD_REGION_SAMPLING_LISTENER: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 117ce58..b215756 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -176,7 +176,12 @@
sidebandStream = NativeHandle::create(input.readNativeHandle(), true);
}
- colorTransform = mat4(static_cast<const float*>(input.readInplace(16 * sizeof(float))));
+ const void* color_transform_data = input.readInplace(16 * sizeof(float));
+ if (color_transform_data) {
+ colorTransform = mat4(static_cast<const float*>(color_transform_data));
+ } else {
+ return BAD_VALUE;
+ }
cornerRadius = input.readFloat();
backgroundBlurRadius = input.readUint32();
cachedBuffer.token = input.readStrongBinder();
@@ -498,4 +503,100 @@
return true;
}
+// ----------------------------------------------------------------------------
+
+status_t CaptureArgs::write(Parcel& output) const {
+ status_t status = output.writeInt32(static_cast<int32_t>(pixelFormat)) ?:
+ output.write(sourceCrop) ?:
+ output.writeFloat(frameScale) ?:
+ output.writeBool(captureSecureLayers);
+ return status;
+}
+
+status_t CaptureArgs::read(const Parcel& input) {
+ int32_t format = 0;
+ status_t status = input.readInt32(&format) ?:
+ input.read(sourceCrop) ?:
+ input.readFloat(&frameScale) ?:
+ input.readBool(&captureSecureLayers);
+
+ pixelFormat = static_cast<ui::PixelFormat>(format);
+ return status;
+}
+
+status_t DisplayCaptureArgs::write(Parcel& output) const {
+ status_t status = CaptureArgs::write(output);
+
+ status |= output.writeStrongBinder(displayToken) ?:
+ output.writeUint32(width) ?:
+ output.writeUint32(height) ?:
+ output.writeBool(useIdentityTransform) ?:
+ output.writeInt32(static_cast<int32_t>(rotation));
+ return status;
+}
+
+status_t DisplayCaptureArgs::read(const Parcel& input) {
+ status_t status = CaptureArgs::read(input);
+
+ int32_t rotationInt = 0;
+
+ status |= input.readStrongBinder(&displayToken) ?:
+ input.readUint32(&width) ?:
+ input.readUint32(&height) ?:
+ input.readBool(&useIdentityTransform) ?:
+ input.readInt32(&rotationInt);
+
+ rotation = ui::toRotation(rotationInt);
+ return status;
+}
+
+status_t LayerCaptureArgs::write(Parcel& output) const {
+ status_t status = CaptureArgs::write(output);
+
+ status |= output.writeStrongBinder(layerHandle);
+ status |= output.writeInt32(excludeHandles.size());
+ for (auto el : excludeHandles) {
+ status |= output.writeStrongBinder(el);
+ }
+ status |= output.writeBool(childrenOnly);
+ return status;
+}
+
+status_t LayerCaptureArgs::read(const Parcel& input) {
+ status_t status = CaptureArgs::read(input);
+
+ status |= input.readStrongBinder(&layerHandle);
+
+ int32_t numExcludeHandles = 0;
+ status |= input.readInt32(&numExcludeHandles);
+ excludeHandles.reserve(numExcludeHandles);
+ for (int i = 0; i < numExcludeHandles; i++) {
+ sp<IBinder> binder;
+ status |= input.readStrongBinder(&binder);
+ excludeHandles.emplace(binder);
+ }
+
+ status |= input.readBool(&childrenOnly);
+ return status;
+}
+
+status_t ScreenCaptureResults::write(Parcel& output) const {
+ status_t status = output.write(*buffer) ?:
+ output.writeBool(capturedSecureLayers) ?:
+ output.writeUint32(static_cast<uint32_t>(capturedDataspace));
+ return status;
+}
+
+status_t ScreenCaptureResults::read(const Parcel& input) {
+ buffer = new GraphicBuffer();
+ uint32_t dataspace = 0;
+ status_t status = input.read(*buffer) ?:
+ input.readBool(&capturedSecureLayers) ?:
+ input.readUint32(&dataspace);
+
+ capturedDataspace = static_cast<ui::Dataspace>(dataspace);
+
+ return status;
+}
+
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a86eafa..e45b3d1 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -732,6 +732,8 @@
mSharedBufferHasBeenQueued = false;
}
+ mDequeuedSlots.insert(buf);
+
return OK;
}
@@ -760,6 +762,8 @@
mSharedBufferHasBeenQueued = true;
}
+ mDequeuedSlots.erase(i);
+
return OK;
}
@@ -895,6 +899,8 @@
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
}
+ mDequeuedSlots.erase(i);
+
if (mEnableFrameTimestamps) {
mFrameEventHistory->applyDelta(output.frameTimestamps);
// Update timestamps with the local acquire fence.
@@ -1513,7 +1519,7 @@
}
int Surface::connect(int api) {
- static sp<IProducerListener> listener = new DummyProducerListener();
+ static sp<IProducerListener> listener = new StubProducerListener();
return connect(api, listener);
}
@@ -1660,6 +1666,7 @@
mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
}
mSlots[attachedSlot].buffer = graphicBuffer;
+ mDequeuedSlots.insert(attachedSlot);
return NO_ERROR;
}
@@ -1926,6 +1933,10 @@
}
void Surface::freeAllBuffers() {
+ if (!mDequeuedSlots.empty()) {
+ ALOGE("%s: %zu buffers were freed while being dequeued!",
+ __FUNCTION__, mDequeuedSlots.size());
+ }
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].buffer = nullptr;
}
@@ -1947,6 +1958,10 @@
ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i);
continue;
}
+ // Don't flush currently dequeued buffers
+ if (mDequeuedSlots.count(i) > 0) {
+ continue;
+ }
outBuffers->push_back(mSlots[i].buffer);
mSlots[i].buffer = nullptr;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 229a5c2..b51bf1f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1922,59 +1922,25 @@
// ----------------------------------------------------------------------------
-status_t ScreenshotClient::capture(const sp<IBinder>& display, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, bool captureSecureLayers,
- sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers) {
+status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs,
+ ScreenCaptureResults& captureResults) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == nullptr) return NO_INIT;
- status_t ret = s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace,
- reqPixelFormat, sourceCrop, reqWidth, reqHeight,
- useIdentityTransform, rotation, captureSecureLayers);
- if (ret != NO_ERROR) {
- return ret;
- }
- return ret;
+ return s->captureDisplay(captureArgs, captureResults);
}
-status_t ScreenshotClient::capture(const sp<IBinder>& display, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, sp<GraphicBuffer>* outBuffer) {
- bool ignored;
- return capture(display, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth, reqHeight,
- useIdentityTransform, rotation, false, outBuffer, ignored);
-}
-
-status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
- sp<GraphicBuffer>* outBuffer) {
+status_t ScreenshotClient::captureDisplay(uint64_t displayOrLayerStack,
+ ScreenCaptureResults& captureResults) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == nullptr) return NO_INIT;
- return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer);
+ return s->captureDisplay(displayOrLayerStack, captureResults);
}
-status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- float frameScale, sp<GraphicBuffer>* outBuffer) {
+status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs,
+ ScreenCaptureResults& captureResults) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == nullptr) return NO_INIT;
- status_t ret = s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat,
- sourceCrop, {}, frameScale, false /* childrenOnly */);
- return ret;
-}
-
-status_t ScreenshotClient::captureChildLayers(
- const sp<IBinder>& layerHandle, ui::Dataspace reqDataSpace, ui::PixelFormat reqPixelFormat,
- const Rect& sourceCrop,
- const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& excludeHandles,
- float frameScale, sp<GraphicBuffer>* outBuffer) {
- sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == nullptr) return NO_INIT;
- status_t ret =
- s->captureLayers(layerHandle, outBuffer, reqDataSpace, reqPixelFormat, sourceCrop,
- excludeHandles, frameScale, true /* childrenOnly */);
- return ret;
+ return s->captureLayers(captureArgs, captureResults);
}
} // namespace android
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index ddd868d..2f538ff 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -499,7 +499,7 @@
// protects static initialization
static Mutex sStaticInitLock;
- // mReleasedTexImageBuffer is a dummy buffer used when in single buffer
+ // mReleasedTexImageBuffer is a buffer placeholder used when in single buffer
// mode and releaseTexImage() has been called
static sp<GraphicBuffer> sReleasedTexImageBuffer;
sp<EglImage> mReleasedTexImage;
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index d7f3492..45e0a13 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -458,7 +458,7 @@
// the producer wants to be notified when the consumer releases a buffer
// back to the BufferQueue. It is also used to detect the death of the
// producer. If only the latter functionality is desired, there is a
- // DummyProducerListener class in IProducerListener.h that can be used.
+ // StubProducerListener class in IProducerListener.h that can be used.
//
// The api should be one of the NATIVE_WINDOW_API_* values in <window.h>
//
diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
index 0b1f4b5..f7ffbb9 100644
--- a/libs/gui/include/gui/IProducerListener.h
+++ b/libs/gui/include/gui/IProducerListener.h
@@ -80,10 +80,9 @@
class BnProducerListener : public IProducerListener {
};
#endif
-class DummyProducerListener : public BnProducerListener
-{
+class StubProducerListener : public BnProducerListener {
public:
- virtual ~DummyProducerListener();
+ virtual ~StubProducerListener();
virtual void onBufferReleased() {}
virtual bool needsReleaseNotify() { return false; }
};
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 645714a..926a66f 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -27,11 +27,11 @@
#include <math/vec4.h>
#include <ui/ConfigStoreTypes.h>
+#include <ui/DisplayId.h>
#include <ui/DisplayedFrameStats.h>
#include <ui/FrameStats.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
-#include <ui/PhysicalDisplayId.h>
#include <ui/PixelFormat.h>
#include <ui/Rotation.h>
@@ -48,11 +48,14 @@
struct client_cache_t;
struct ComposerState;
+struct DisplayCaptureArgs;
struct DisplayConfig;
struct DisplayInfo;
struct DisplayStatInfo;
struct DisplayState;
struct InputWindowCommands;
+struct LayerCaptureArgs;
+struct ScreenCaptureResults;
class LayerDebugInfo;
class HdrCapabilities;
class IDisplayEventConnection;
@@ -246,65 +249,17 @@
/**
* Capture the specified screen. This requires READ_FRAME_BUFFER
* permission. This function will fail if there is a secure window on
- * screen.
+ * screen and DisplayCaptureArgs.captureSecureLayers is false.
*
* This function can capture a subregion (the source crop) of the screen.
* The subregion can be optionally rotated. It will also be scaled to
* match the size of the output buffer.
- *
- * reqDataspace and reqPixelFormat specify the data space and pixel format
- * of the buffer. The caller should pick the data space and pixel format
- * that it can consume.
- *
- * sourceCrop is the crop on the logical display.
- *
- * reqWidth and reqHeight specifies the size of the buffer. When either
- * of them is 0, they are set to the size of the logical display viewport.
- *
- * When useIdentityTransform is true, layer transformations are disabled.
- *
- * rotation specifies the rotation of the source crop (and the pixels in
- * it) around its center.
*/
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- bool& outCapturedSecureLayers, ui::Dataspace reqDataspace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation = ui::ROTATION_0,
- bool captureSecureLayers = false) = 0;
- /**
- * Capture the specified screen. This requires READ_FRAME_BUFFER
- * permission. This function will fail if there is a secure window on
- * screen.
- *
- * This function can capture a subregion (the source crop) of the screen
- * into an sRGB buffer with RGBA_8888 pixel format.
- * The subregion can be optionally rotated. It will also be scaled to
- * match the size of the output buffer.
- *
- * At the moment, sourceCrop is ignored and is always set to the visible
- * region (projected display viewport) of the screen.
- *
- * reqWidth and reqHeight specifies the size of the buffer. When either
- * of them is 0, they are set to the size of the logical display viewport.
- *
- * When useIdentityTransform is true, layer transformations are disabled.
- *
- * rotation specifies the rotation of the source crop (and the pixels in
- * it) around its center.
- */
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- bool useIdentityTransform,
- ui::Rotation rotation = ui::ROTATION_0) {
- bool outIgnored;
- return captureScreen(display, outBuffer, outIgnored, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, sourceCrop, reqWidth, reqHeight,
- useIdentityTransform, rotation);
- }
+ virtual status_t captureDisplay(const DisplayCaptureArgs& args,
+ ScreenCaptureResults& captureResults) = 0;
- virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
- sp<GraphicBuffer>* outBuffer) = 0;
+ virtual status_t captureDisplay(uint64_t displayOrLayerStack,
+ ScreenCaptureResults& captureResults) = 0;
template <class AA>
struct SpHash {
@@ -313,27 +268,11 @@
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
- *
- * reqDataspace and reqPixelFormat specify the data space and pixel format
- * of the buffer. The caller should pick the data space and pixel format
- * that it can consume.
+ * This requires READ_FRAME_BUFFER permission. This function will fail if there
+ * is a secure window on screen
*/
- virtual status_t captureLayers(
- const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
- ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& excludeHandles,
- float frameScale = 1.0, bool childrenOnly = false) = 0;
-
- /**
- * Capture a subtree of the layer hierarchy into an sRGB buffer with RGBA_8888 pixel format,
- * potentially ignoring the root node.
- */
- status_t captureLayers(const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
- const Rect& sourceCrop, float frameScale = 1.0,
- bool childrenOnly = false) {
- return captureLayers(layerHandleBinder, outBuffer, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, sourceCrop, {}, frameScale, childrenOnly);
- }
+ virtual status_t captureLayers(const LayerCaptureArgs& args,
+ ScreenCaptureResults& captureResults) = 0;
/* Clears the frame statistics for animations.
*
@@ -562,7 +501,7 @@
GET_DISPLAY_CONFIGS,
GET_ACTIVE_CONFIG,
GET_DISPLAY_STATE,
- CAPTURE_SCREEN,
+ CAPTURE_DISPLAY,
CAPTURE_LAYERS,
CLEAR_ANIMATION_FRAME_STATS,
GET_ANIMATION_FRAME_STATS,
@@ -590,7 +529,7 @@
GET_DESIRED_DISPLAY_CONFIG_SPECS,
GET_DISPLAY_BRIGHTNESS_SUPPORT,
SET_DISPLAY_BRIGHTNESS,
- CAPTURE_SCREEN_BY_ID,
+ CAPTURE_DISPLAY_BY_ID,
NOTIFY_POWER_BOOST,
SET_GLOBAL_SHADOW_SETTINGS,
GET_AUTO_LOW_LATENCY_MODE_SUPPORT,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 41aad0d..de3a9a7 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -30,6 +30,7 @@
#include <input/InputWindow.h>
#endif
+#include <gui/ISurfaceComposer.h>
#include <gui/LayerMetadata.h>
#include <math/vec3.h>
#include <ui/GraphicTypes.h>
@@ -312,6 +313,47 @@
// functionName can be null.
bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName);
+struct CaptureArgs {
+ virtual ~CaptureArgs() = default;
+
+ ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888};
+ Rect sourceCrop;
+ float frameScale{1};
+ bool captureSecureLayers{false};
+
+ virtual status_t write(Parcel& output) const;
+ virtual status_t read(const Parcel& input);
+};
+
+struct DisplayCaptureArgs : CaptureArgs {
+ sp<IBinder> displayToken;
+ uint32_t width{0};
+ uint32_t height{0};
+ bool useIdentityTransform{false};
+ ui::Rotation rotation{ui::ROTATION_0};
+
+ status_t write(Parcel& output) const override;
+ status_t read(const Parcel& input) override;
+};
+
+struct LayerCaptureArgs : CaptureArgs {
+ sp<IBinder> layerHandle;
+ std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> excludeHandles;
+ bool childrenOnly{true};
+
+ status_t write(Parcel& output) const override;
+ status_t read(const Parcel& input) override;
+};
+
+struct ScreenCaptureResults {
+ sp<GraphicBuffer> buffer;
+ bool capturedSecureLayers{false};
+ ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB};
+
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
+};
+
}; // namespace android
#endif // ANDROID_SF_LAYER_STATE_H
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 49c83da..55b4101 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -30,6 +30,7 @@
#include <utils/RefBase.h>
#include <shared_mutex>
+#include <unordered_set>
namespace android {
@@ -543,8 +544,15 @@
int mMaxBufferCount;
sp<IProducerListener> mListenerProxy;
+
+ // Get and flush the buffers of given slots, if the buffer in the slot
+ // is currently dequeued then it won't be flushed and won't be returned
+ // in outBuffers.
status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
std::vector<sp<GraphicBuffer>>* outBuffers);
+
+ // Buffers that are successfully dequeued/attached and handed to clients
+ std::unordered_set<int> mDequeuedSlots;
};
} // namespace android
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index d5ca0f6..1a9710a 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -597,26 +597,12 @@
public:
// if cropping isn't required, callers may pass in a default Rect, e.g.:
// capture(display, producer, Rect(), reqWidth, ...);
- static status_t capture(const sp<IBinder>& display, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, bool captureSecureLayers,
- sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers);
- static status_t capture(const sp<IBinder>& display, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, sp<GraphicBuffer>* outBuffer);
- static status_t capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
- sp<GraphicBuffer>* outBuffer);
- static status_t captureLayers(const sp<IBinder>& layerHandle, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- float frameScale, sp<GraphicBuffer>* outBuffer);
- static status_t captureChildLayers(
- const sp<IBinder>& layerHandle, ui::Dataspace reqDataSpace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>&
- excludeHandles,
- float frameScale, sp<GraphicBuffer>* outBuffer);
+ static status_t captureDisplay(const DisplayCaptureArgs& captureArgs,
+ ScreenCaptureResults& captureResults);
+ static status_t captureDisplay(uint64_t displayOrLayerStack,
+ ScreenCaptureResults& captureResults);
+ static status_t captureLayers(const LayerCaptureArgs& captureArgs,
+ ScreenCaptureResults& captureResults);
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
index 99ab085..004d875 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/WGraphicBufferProducer.h
@@ -51,12 +51,14 @@
typedef ::android::IProducerListener BProducerListener;
#ifndef LOG
-struct LOG_dummy {
+struct LOG_stub {
template <typename T>
- LOG_dummy& operator<< (const T&) { return *this; }
+ LOG_stub& operator<<(const T&) {
+ return *this;
+ }
};
-#define LOG(x) LOG_dummy()
+#define LOG(x) LOG_stub()
#endif
// Instantiate only if HGraphicBufferProducer is base of BASE.
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index d929a59..d88c477 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -120,6 +120,8 @@
.show(mSurfaceControl)
.setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
.apply();
+
+ mCaptureArgs.displayToken = mDisplayToken;
}
void setUpProducer(BLASTBufferQueueHelper adapter, sp<IGraphicBufferProducer>& producer) {
@@ -128,7 +130,7 @@
ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(2));
IGraphicBufferProducer::QueueBufferOutput qbOutput;
ASSERT_EQ(NO_ERROR,
- igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
+ igbProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false,
&qbOutput));
ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
producer = igbProducer;
@@ -165,14 +167,15 @@
void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region, int32_t border = 0,
bool outsideRegion = false) {
+ sp<GraphicBuffer>& captureBuf = mCaptureResults.buffer;
const auto epsilon = 3;
- const auto width = mScreenCaptureBuf->getWidth();
- const auto height = mScreenCaptureBuf->getHeight();
- const auto stride = mScreenCaptureBuf->getStride();
+ const auto width = captureBuf->getWidth();
+ const auto height = captureBuf->getHeight();
+ const auto stride = captureBuf->getStride();
uint32_t* bufData;
- mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
- reinterpret_cast<void**>(&bufData));
+ captureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
+ reinterpret_cast<void**>(&bufData));
for (uint32_t row = 0; row < height; row++) {
for (uint32_t col = 0; col < width; col++) {
@@ -196,7 +199,7 @@
}
}
}
- mScreenCaptureBuf->unlock();
+ captureBuf->unlock();
ASSERT_EQ(false, ::testing::Test::HasFailure());
}
@@ -206,10 +209,12 @@
sp<IBinder> mDisplayToken;
sp<SurfaceControl> mSurfaceControl;
- sp<GraphicBuffer> mScreenCaptureBuf;
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
+
+ DisplayCaptureArgs mCaptureArgs;
+ ScreenCaptureResults mCaptureResults;
};
TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
@@ -301,12 +306,7 @@
adapter.waitForCallbacks();
// capture screen and verify that it is red
- bool capturedSecureLayers;
- ASSERT_EQ(NO_ERROR,
- mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
- mDisplayWidth, mDisplayHeight,
- /*useIdentityTransform*/ false));
+ ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
}
@@ -383,12 +383,8 @@
adapter.waitForCallbacks();
// capture screen and verify that it is red
- bool capturedSecureLayers;
- ASSERT_EQ(NO_ERROR,
- mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
- mDisplayWidth, mDisplayHeight,
- /*useIdentityTransform*/ false));
+ ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
}
@@ -444,12 +440,8 @@
adapter.waitForCallbacks();
// capture screen and verify that it is red
- bool capturedSecureLayers;
- ASSERT_EQ(NO_ERROR,
- mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
- mDisplayWidth, mDisplayHeight,
- /*useIdentityTransform*/ false));
+ ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b,
{0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}));
@@ -489,12 +481,8 @@
ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
adapter.waitForCallbacks();
- bool capturedSecureLayers;
- ASSERT_EQ(NO_ERROR,
- mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
- Rect(), mDisplayWidth, mDisplayHeight,
- /*useIdentityTransform*/ false));
+ ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+
switch (tr) {
case ui::Transform::ROT_0:
ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0,
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index b87cbbd..fc6551c 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -51,7 +51,7 @@
mBFL = new BufferFreedListener(this);
mBIC->setBufferFreedListener(mBFL);
- sp<IProducerListener> producerListener = new DummyProducerListener();
+ sp<IProducerListener> producerListener = new StubProducerListener();
IGraphicBufferProducer::QueueBufferOutput bufferOutput;
ASSERT_EQ(NO_ERROR,
mProducer->connect(producerListener, NATIVE_WINDOW_API_CPU,
@@ -131,7 +131,7 @@
// Test that detaching buffer from consumer side triggers onBufferFreed.
TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromConsumer) {
int slot;
- // Producer: generate a dummy buffer.
+ // Producer: generate a placeholder buffer.
DequeueBuffer(&slot);
QueueBuffer(slot);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 6d7b6bb..d1208ee 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "BufferQueue_test"
//#define LOG_NDEBUG 0
-#include "DummyConsumer.h"
+#include "MockConsumer.h"
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
@@ -134,8 +134,8 @@
mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
EXPECT_TRUE(mConsumer != nullptr);
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
ASSERT_EQ(OK,
mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
@@ -171,23 +171,22 @@
TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- mConsumer->consumerConnect(dc, false);
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
int bufferCount = 50;
mConsumer->setMaxBufferCount(bufferCount);
IGraphicBufferProducer::QueueBufferOutput output;
- mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
ASSERT_EQ(output.maxBufferCount, bufferCount);
}
TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- mConsumer->consumerConnect(dc, false);
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
IGraphicBufferProducer::QueueBufferOutput qbo;
- mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
- &qbo);
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
mProducer->setMaxDequeuedBufferCount(3);
int slot;
@@ -219,15 +218,14 @@
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- mConsumer->consumerConnect(dc, false);
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
IGraphicBufferProducer::QueueBufferOutput qbo;
- mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
- &qbo);
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
mProducer->setMaxDequeuedBufferCount(3);
int minBufferCount;
@@ -263,12 +261,11 @@
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- mConsumer->consumerConnect(dc, false);
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
IGraphicBufferProducer::QueueBufferOutput qbo;
- mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
- &qbo);
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
mProducer->setMaxDequeuedBufferCount(2);
int minBufferCount;
@@ -310,8 +307,8 @@
TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- mConsumer->consumerConnect(dc, false);
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
// Test shared buffer mode
EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
@@ -319,8 +316,8 @@
TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- mConsumer->consumerConnect(dc, false);
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
@@ -332,11 +329,11 @@
TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
@@ -386,11 +383,11 @@
TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
int slot;
sp<Fence> fence;
@@ -445,11 +442,11 @@
TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
int slot;
sp<Fence> fence;
@@ -488,11 +485,11 @@
TEST_F(BufferQueueTest, TestDisallowingAllocation) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
static const uint32_t WIDTH = 320;
static const uint32_t HEIGHT = 240;
@@ -526,11 +523,11 @@
TEST_F(BufferQueueTest, TestGenerationNumbers) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
@@ -568,11 +565,11 @@
TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
@@ -618,11 +615,11 @@
TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
@@ -687,11 +684,11 @@
TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
// Dequeue a buffer
int sharedSlot;
@@ -738,11 +735,11 @@
TEST_F(BufferQueueTest, TestTimeouts) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
// Fill up the queue. Since the controlledByApp flags are set to true, this
// queue should be in non-blocking mode, and we should be recycling the same
@@ -800,11 +797,11 @@
TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> sourceFence;
@@ -822,11 +819,11 @@
TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
// Dequeue and queue the first buffer, storing the handle
int slot = BufferQueue::INVALID_BUFFER_SLOT;
@@ -876,11 +873,11 @@
TEST_F(BufferQueueTest, TestOccupancyHistory) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> fence = Fence::NO_FENCE;
@@ -1030,8 +1027,8 @@
TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
ASSERT_EQ(OK, mProducer->connect(pl,
@@ -1115,11 +1112,11 @@
TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(OK,
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
int slot = BufferQueue::INVALID_BUFFER_SLOT;
@@ -1156,12 +1153,11 @@
TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- sp<IProducerListener> dummyListener(new DummyProducerListener);
- ASSERT_EQ(OK, mProducer->connect(dummyListener, NATIVE_WINDOW_API_CPU,
- true, &output));
+ sp<IProducerListener> fakeListener(new StubProducerListener);
+ ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> fence = Fence::NO_FENCE;
@@ -1215,15 +1211,13 @@
TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
createBufferQueue();
- sp<DummyConsumer> dc(new DummyConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ sp<MockConsumer> mc(new MockConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
IGraphicBufferProducer::QueueBufferOutput output;
- sp<IProducerListener> dummyListener(new DummyProducerListener);
+ sp<IProducerListener> fakeListener(new StubProducerListener);
ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
- ASSERT_EQ(OK, mProducer->connect(
- dummyListener, NATIVE_WINDOW_API_CPU, true, &output));
- ASSERT_EQ(BAD_VALUE, mProducer->connect(
- dummyListener, NATIVE_WINDOW_API_MEDIA, true, &output));
+ ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
+ ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index cca8ddd..a68ec29 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -63,6 +63,7 @@
// We use the top 10 layers as a way to haphazardly place ourselves above anything else.
static const int LAYER_BASE = INT32_MAX - 10;
+static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
class InputSurface {
public:
@@ -206,7 +207,8 @@
InputApplicationInfo aInfo;
aInfo.token = new BBinder();
aInfo.name = "Test app info";
- aInfo.dispatchingTimeout = 5s;
+ aInfo.dispatchingTimeoutMillis =
+ std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
mInputInfo.applicationInfo = aInfo;
}
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 103f775..15bd32d 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "IGraphicBufferProducer_test"
//#define LOG_NDEBUG 0
-#include "DummyConsumer.h"
+#include "MockConsumer.h"
#include <gtest/gtest.h>
@@ -89,7 +89,7 @@
ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
testInfo->name());
- mDC = new DummyConsumer;
+ mMC = new MockConsumer;
switch (GetParam()) {
case USE_BUFFER_QUEUE_PRODUCER: {
@@ -114,7 +114,7 @@
}
// Must connect consumer before producer connects will succeed.
- ASSERT_OK(mConsumer->consumerConnect(mDC, /*controlledByApp*/false));
+ ASSERT_OK(mConsumer->consumerConnect(mMC, /*controlledByApp*/ false));
}
virtual void TearDown() {
@@ -249,7 +249,7 @@
}
private: // hide from test body
- sp<DummyConsumer> mDC;
+ sp<MockConsumer> mMC;
protected: // accessible from test body
sp<IGraphicBufferProducer> mProducer;
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index acd4297..58d7cc6 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -129,7 +129,7 @@
int32_t mExpectedSlot = 0;
};
-class DummyListener : public BnConsumerListener {
+class FakeListener : public BnConsumerListener {
public:
void onFrameAvailable(const BufferItem&) override {}
void onBuffersReleased() override {}
@@ -140,7 +140,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<IConsumerListener> listener = new DummyListener;
+ sp<IConsumerListener> listener = new FakeListener;
consumer->consumerConnect(listener, false);
sp<MaliciousBQP> malicious = new MaliciousBQP(producer);
diff --git a/libs/gui/tests/DummyConsumer.h b/libs/gui/tests/MockConsumer.h
similarity index 94%
rename from libs/gui/tests/DummyConsumer.h
rename to libs/gui/tests/MockConsumer.h
index 502bdf9..4a6c51c 100644
--- a/libs/gui/tests/DummyConsumer.h
+++ b/libs/gui/tests/MockConsumer.h
@@ -18,7 +18,7 @@
namespace android {
-struct DummyConsumer : public BnConsumerListener {
+struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index ad6e051..b65cdda 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -48,7 +48,7 @@
}
};
-struct DummyListener : public BnConsumerListener {
+struct FakeListener : public BnConsumerListener {
virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
@@ -64,7 +64,7 @@
sp<IGraphicBufferProducer> outputProducer;
sp<IGraphicBufferConsumer> outputConsumer;
BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
- ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
+ ASSERT_EQ(OK, outputConsumer->consumerConnect(new FakeListener, false));
sp<StreamSplitter> splitter;
status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
@@ -75,8 +75,9 @@
ASSERT_EQ(OK, outputProducer->allowAllocation(false));
IGraphicBufferProducer::QueueBufferOutput qbOutput;
- ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &qbOutput));
+ ASSERT_EQ(OK,
+ inputProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false,
+ &qbOutput));
int slot;
sp<Fence> fence;
@@ -132,8 +133,7 @@
for (int output = 0; output < NUM_OUTPUTS; ++output) {
BufferQueue::createBufferQueue(&outputProducers[output],
&outputConsumers[output]);
- ASSERT_EQ(OK, outputConsumers[output]->consumerConnect(
- new DummyListener, false));
+ ASSERT_EQ(OK, outputConsumers[output]->consumerConnect(new FakeListener, false));
}
sp<StreamSplitter> splitter;
@@ -147,8 +147,9 @@
}
IGraphicBufferProducer::QueueBufferOutput qbOutput;
- ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &qbOutput));
+ ASSERT_EQ(OK,
+ inputProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false,
+ &qbOutput));
int slot;
sp<Fence> fence;
@@ -203,7 +204,7 @@
sp<IGraphicBufferProducer> outputProducer;
sp<IGraphicBufferConsumer> outputConsumer;
BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
- ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
+ ASSERT_EQ(OK, outputConsumer->consumerConnect(new FakeListener, false));
sp<StreamSplitter> splitter;
status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
@@ -211,8 +212,9 @@
ASSERT_EQ(OK, splitter->addOutput(outputProducer));
IGraphicBufferProducer::QueueBufferOutput qbOutput;
- ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
- NATIVE_WINDOW_API_CPU, false, &qbOutput));
+ ASSERT_EQ(OK,
+ inputProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false,
+ &qbOutput));
int slot;
sp<Fence> fence;
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index c85e844..c7458a3 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -54,7 +54,7 @@
mANW = mSTC;
// We need a valid GL context so we can test updateTexImage()
- // This initializes EGL and create a dummy GL context with a
+ // This initializes EGL and create a GL context placeholder with a
// pbuffer render target.
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 6d92143..2f8e412 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "DummyConsumer.h"
+#include "MockConsumer.h"
#include <gtest/gtest.h>
@@ -56,12 +56,11 @@
static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max();
-class DummySurfaceListener : public SurfaceListener {
+class FakeSurfaceListener : public SurfaceListener {
public:
- DummySurfaceListener(bool enableReleasedCb = false) :
- mEnableReleaseCb(enableReleasedCb),
- mBuffersReleased(0) {}
- virtual ~DummySurfaceListener() = default;
+ FakeSurfaceListener(bool enableReleasedCb = false)
+ : mEnableReleaseCb(enableReleasedCb), mBuffersReleased(0) {}
+ virtual ~FakeSurfaceListener() = default;
virtual void onBufferReleased() {
mBuffersReleased++;
@@ -124,15 +123,15 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
sp<ANativeWindow> window(surface);
- sp<DummySurfaceListener> listener;
+ sp<FakeSurfaceListener> listener;
if (hasSurfaceListener) {
- listener = new DummySurfaceListener(enableReleasedCb);
+ listener = new FakeSurfaceListener(enableReleasedCb);
}
ASSERT_EQ(OK, surface->connect(
NATIVE_WINDOW_API_CPU,
@@ -245,11 +244,13 @@
const sp<IBinder> display = sf->getInternalDisplayToken();
ASSERT_FALSE(display == nullptr);
- sp<GraphicBuffer> outBuffer;
- bool ignored;
- ASSERT_EQ(NO_ERROR,
- sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false));
+ DisplayCaptureArgs captureArgs;
+ captureArgs.displayToken = display;
+ captureArgs.width = 64;
+ captureArgs.height = 64;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults));
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
NATIVE_WINDOW_API_CPU));
@@ -279,9 +280,7 @@
&buf));
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
}
- ASSERT_EQ(NO_ERROR,
- sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false));
+ ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults));
}
TEST_F(SurfaceTest, ConcreteTypeIsSurface) {
@@ -381,8 +380,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
@@ -397,8 +396,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
@@ -428,8 +427,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
@@ -452,8 +451,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
@@ -497,8 +496,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
@@ -523,13 +522,13 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setConsumerName(String8("TestConsumer"));
sp<Surface> surface = new Surface(producer);
sp<ANativeWindow> window(surface);
- sp<DummyProducerListener> listener = new DummyProducerListener();
+ sp<StubProducerListener> listener = new StubProducerListener();
ASSERT_EQ(OK, surface->connect(
NATIVE_WINDOW_API_CPU,
/*listener*/listener,
@@ -743,12 +742,8 @@
}
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
ColorMode /*colorMode*/) override { return NO_ERROR; }
- status_t captureScreen(const sp<IBinder>& /*display*/, sp<GraphicBuffer>* /*outBuffer*/,
- bool& /*outCapturedSecureLayers*/, ui::Dataspace /*reqDataspace*/,
- ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/,
- uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
- bool /*useIdentityTransform*/, ui::Rotation,
- bool /*captureSecureLayers*/) override {
+ status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */,
+ ScreenCaptureResults& /* captureResults */) override {
return NO_ERROR;
}
status_t getAutoLowLatencyModeSupport(const sp<IBinder>& /*display*/,
@@ -761,17 +756,12 @@
return NO_ERROR;
}
void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {}
- status_t captureScreen(uint64_t /*displayOrLayerStack*/, ui::Dataspace* /*outDataspace*/,
- sp<GraphicBuffer>* /*outBuffer*/) override {
+ status_t captureDisplay(uint64_t /*displayOrLayerStack*/,
+ ScreenCaptureResults& /* captureResults */) override {
return NO_ERROR;
}
- virtual status_t captureLayers(
- const sp<IBinder>& /*parentHandle*/, sp<GraphicBuffer>* /*outBuffer*/,
- ui::Dataspace /*reqDataspace*/, ui::PixelFormat /*reqPixelFormat*/,
- const Rect& /*sourceCrop*/,
- const std::unordered_set<sp<IBinder>,
- ISurfaceComposer::SpHash<IBinder>>& /*excludeHandles*/,
- float /*frameScale*/, bool /*childrenOnly*/) override {
+ virtual status_t captureLayers(const LayerCaptureArgs& /* captureArgs */,
+ ScreenCaptureResults& /* captureResults */) override {
return NO_ERROR;
}
status_t clearAnimationFrameStats() override { return NO_ERROR; }
@@ -1910,8 +1900,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
consumer->setDefaultBufferSize(10, 10);
sp<Surface> surface = new Surface(producer);
@@ -1980,8 +1970,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- sp<DummyConsumer> dummyConsumer(new DummyConsumer);
- consumer->consumerConnect(dummyConsumer, false);
+ sp<MockConsumer> mockConsumer(new MockConsumer);
+ consumer->consumerConnect(mockConsumer, false);
sp<Surface> surface = new Surface(producer);
sp<ANativeWindow> window(surface);
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 7dd5276..0c3c1f0 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -14,6 +14,13 @@
// libinput is partially built for the host (used by build time keymap validation tool)
+filegroup {
+ name: "inputconstants_aidl",
+ srcs: [
+ "android/os/IInputConstants.aidl",
+ ],
+}
+
cc_library {
name: "libinput",
host_supported: true,
@@ -54,13 +61,14 @@
target: {
android: {
srcs: [
- "InputApplication.cpp",
"InputTransport.cpp",
"InputWindow.cpp",
"LatencyStatistics.cpp",
"VelocityControl.cpp",
"VelocityTracker.cpp",
"android/FocusRequest.aidl",
+ "android/InputApplicationInfo.aidl",
+ "android/os/IInputConstants.aidl",
"android/os/IInputFlinger.aidl",
"android/os/ISetInputWindowsListener.aidl",
],
diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp
deleted file mode 100644
index 41721a7..0000000
--- a/libs/input/InputApplication.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "InputApplication"
-
-#include <input/InputApplication.h>
-
-#include <android/log.h>
-
-namespace android {
-
-status_t InputApplicationInfo::readFromParcel(const android::Parcel* parcel) {
- if (parcel == nullptr) {
- ALOGE("%s: Null parcel", __func__);
- return BAD_VALUE;
- }
- token = parcel->readStrongBinder();
- dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64());
- status_t status = parcel->readUtf8FromUtf16(&name);
-
- return status;
-}
-
-status_t InputApplicationInfo::writeToParcel(android::Parcel* parcel) const {
- if (parcel == nullptr) {
- ALOGE("%s: Null parcel", __func__);
- return BAD_VALUE;
- }
- status_t status = parcel->writeStrongBinder(token)
- ?: parcel->writeInt64(dispatchingTimeout.count())
- ?: parcel->writeUtf8AsUtf16(name) ;
-
- return status;
-}
-
-// --- InputApplicationHandle ---
-
-InputApplicationHandle::InputApplicationHandle() {}
-
-InputApplicationHandle::~InputApplicationHandle() {}
-
-} // namespace android
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 51190a0..6db9ed5 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -57,17 +57,15 @@
info.frameLeft == frameLeft && info.frameTop == frameTop &&
info.frameRight == frameRight && info.frameBottom == frameBottom &&
info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor &&
- info.transform == transform &&
- info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible &&
- info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay &&
- info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper &&
- info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid &&
+ info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) &&
+ info.visible == visible && info.canReceiveKeys == canReceiveKeys &&
+ info.trustedOverlay == trustedOverlay && info.hasFocus == hasFocus &&
+ info.hasWallpaper == hasWallpaper && info.paused == paused &&
+ info.ownerPid == ownerPid && info.ownerUid == ownerUid &&
info.inputFeatures == inputFeatures && info.displayId == displayId &&
info.portalToDisplayId == portalToDisplayId &&
info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
- info.applicationInfo.name == applicationInfo.name &&
- info.applicationInfo.token == applicationInfo.token &&
- info.applicationInfo.dispatchingTimeout == applicationInfo.dispatchingTimeout;
+ info.applicationInfo == applicationInfo;
}
status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const {
diff --git a/libs/input/android/InputApplicationInfo.aidl b/libs/input/android/InputApplicationInfo.aidl
new file mode 100644
index 0000000..9336039
--- /dev/null
+++ b/libs/input/android/InputApplicationInfo.aidl
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android;
+
+parcelable InputApplicationInfo {
+ @nullable IBinder token;
+ @utf8InCpp String name;
+ long dispatchingTimeoutMillis;
+}
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
new file mode 100644
index 0000000..82c220f
--- /dev/null
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+
+/** @hide */
+interface IInputConstants
+{
+ const int DEFAULT_DISPATCHING_TIMEOUT_MILLIS = 5000; // 5 seconds
+}
diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp
index 1b58460..7e3a40d 100644
--- a/libs/input/tests/InputWindow_test.cpp
+++ b/libs/input/tests/InputWindow_test.cpp
@@ -66,6 +66,9 @@
i.portalToDisplayId = 2;
i.replaceTouchableRegionWithCrop = true;
i.touchableRegionCropHandle = touchableRegionCropHandle;
+ i.applicationInfo.name = "ApplicationFooBar";
+ i.applicationInfo.token = new BBinder();
+ i.applicationInfo.dispatchingTimeoutMillis = 0x12345678ABCD;
Parcel p;
i.writeToParcel(&p);
@@ -97,6 +100,21 @@
ASSERT_EQ(i.portalToDisplayId, i2.portalToDisplayId);
ASSERT_EQ(i.replaceTouchableRegionWithCrop, i2.replaceTouchableRegionWithCrop);
ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle);
+ ASSERT_EQ(i.applicationInfo, i2.applicationInfo);
+}
+
+TEST(InputApplicationInfo, Parcelling) {
+ InputApplicationInfo i;
+ i.token = new BBinder();
+ i.name = "ApplicationFooBar";
+ i.dispatchingTimeoutMillis = 0x12345678ABCD;
+
+ Parcel p;
+ ASSERT_EQ(i.writeToParcel(&p), OK);
+ p.setDataPosition(0);
+ InputApplicationInfo i2;
+ ASSERT_EQ(i2.readFromParcel(&p), OK);
+ ASSERT_EQ(i, i2);
}
} // namespace test
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index e458b2e..ebc8909 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -363,9 +363,8 @@
}
void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool connected) {
- ALOGV("choreographer %p ~ received hotplug event (displayId=%"
- ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", connected=%s), ignoring.",
- this, displayId, toString(connected));
+ ALOGV("choreographer %p ~ received hotplug event (displayId=%s, connected=%s), ignoring.",
+ this, to_string(displayId).c_str(), toString(connected));
}
// TODO(b/74619554): The PhysicalDisplayId is ignored because currently
@@ -375,9 +374,8 @@
// PhysicalDisplayId should no longer be ignored.
void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, int32_t configId,
nsecs_t vsyncPeriod) {
- ALOGV("choreographer %p ~ received config change event "
- "(displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%d).",
- this, displayId, configId);
+ ALOGV("choreographer %p ~ received config change event (displayId=%s, configId=%d).",
+ this, to_string(displayId).c_str(), configId);
const nsecs_t lastPeriod = mLatestVsyncPeriod;
std::vector<RefreshRateCallback> callbacks{};
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index d102696..6b18848 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -245,22 +245,22 @@
// if can't create a GL context, we can only abort.
LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
- EGLSurface dummy = EGL_NO_SURFACE;
+ EGLSurface stub = EGL_NO_SURFACE;
if (!extensions.hasSurfacelessContext()) {
- dummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
- Protection::UNPROTECTED);
- LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
+ stub = createStubEglPbufferSurface(display, config, args.pixelFormat,
+ Protection::UNPROTECTED);
+ LOG_ALWAYS_FATAL_IF(stub == EGL_NO_SURFACE, "can't create stub pbuffer");
}
- EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
- LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
+ EGLBoolean success = eglMakeCurrent(display, stub, stub, ctxt);
+ LOG_ALWAYS_FATAL_IF(!success, "can't make stub pbuffer current");
extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
- EGLSurface protectedDummy = EGL_NO_SURFACE;
+ EGLSurface protectedStub = EGL_NO_SURFACE;
if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
- protectedDummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
- Protection::PROTECTED);
- ALOGE_IF(protectedDummy == EGL_NO_SURFACE, "can't create protected dummy pbuffer");
+ protectedStub = createStubEglPbufferSurface(display, config, args.pixelFormat,
+ Protection::PROTECTED);
+ ALOGE_IF(protectedStub == EGL_NO_SURFACE, "can't create protected stub pbuffer");
}
// now figure out what version of GL did we actually get
@@ -278,8 +278,8 @@
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, dummy,
- protectedContext, protectedDummy);
+ engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, stub,
+ protectedContext, protectedStub);
break;
}
@@ -334,15 +334,15 @@
}
GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
- EGLConfig config, EGLContext ctxt, EGLSurface dummy,
- EGLContext protectedContext, EGLSurface protectedDummy)
+ EGLConfig config, EGLContext ctxt, EGLSurface stub,
+ EGLContext protectedContext, EGLSurface protectedStub)
: renderengine::impl::RenderEngine(args),
mEGLDisplay(display),
mEGLConfig(config),
mEGLContext(ctxt),
- mDummySurface(dummy),
+ mStubSurface(stub),
mProtectedEGLContext(protectedContext),
- mProtectedDummySurface(protectedDummy),
+ mProtectedStubSurface(protectedStub),
mVpWidth(0),
mVpHeight(0),
mFramebufferImageCacheSize(args.imageCacheSize),
@@ -355,12 +355,12 @@
// Initialize protected EGL Context.
if (mProtectedEGLContext != EGL_NO_CONTEXT) {
- EGLBoolean success = eglMakeCurrent(display, mProtectedDummySurface, mProtectedDummySurface,
+ EGLBoolean success = eglMakeCurrent(display, mProtectedStubSurface, mProtectedStubSurface,
mProtectedEGLContext);
ALOGE_IF(!success, "can't make protected context current");
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
- success = eglMakeCurrent(display, mDummySurface, mDummySurface, mEGLContext);
+ success = eglMakeCurrent(display, mStubSurface, mStubSurface, mEGLContext);
LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
}
@@ -896,7 +896,7 @@
return false;
}
- // Bind the texture to dummy data so that backing image data can be freed.
+ // Bind the texture to placeholder so that backing image data can be freed.
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
// Release the cached fence here, so that we don't churn reallocations when
@@ -934,7 +934,7 @@
if (useProtectedContext && mProtectedEGLContext == EGL_NO_CONTEXT) {
return false;
}
- const EGLSurface surface = useProtectedContext ? mProtectedDummySurface : mDummySurface;
+ const EGLSurface surface = useProtectedContext ? mProtectedStubSurface : mStubSurface;
const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
if (success) {
@@ -1566,11 +1566,11 @@
return context;
}
-EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
- int hwcFormat, Protection protection) {
- EGLConfig dummyConfig = config;
- if (dummyConfig == EGL_NO_CONFIG) {
- dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
+EGLSurface GLESRenderEngine::createStubEglPbufferSurface(EGLDisplay display, EGLConfig config,
+ int hwcFormat, Protection protection) {
+ EGLConfig stubConfig = config;
+ if (stubConfig == EGL_NO_CONFIG) {
+ stubConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
std::vector<EGLint> attributes;
attributes.reserve(7);
@@ -1584,7 +1584,7 @@
}
attributes.push_back(EGL_NONE);
- return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
+ return eglCreatePbufferSurface(display, stubConfig, attributes.data());
}
bool GLESRenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 9ab5ee6..245bfd7 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -53,8 +53,8 @@
static std::unique_ptr<GLESRenderEngine> create(const RenderEngineCreationArgs& args);
GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config,
- EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext,
- EGLSurface protectedDummy);
+ EGLContext ctxt, EGLSurface stub, EGLContext protectedContext,
+ EGLSurface protectedStub);
~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
void primeCache() const override;
@@ -115,8 +115,8 @@
static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
EGLContext shareContext, bool useContextPriority,
Protection protection);
- static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
- int hwcFormat, Protection protection);
+ static EGLSurface createStubEglPbufferSurface(EGLDisplay display, EGLConfig config,
+ int hwcFormat, Protection protection);
std::unique_ptr<Framebuffer> createFramebuffer();
std::unique_ptr<Image> createImage();
void checkErrors() const;
@@ -175,9 +175,9 @@
EGLDisplay mEGLDisplay;
EGLConfig mEGLConfig;
EGLContext mEGLContext;
- EGLSurface mDummySurface;
+ EGLSurface mStubSurface;
EGLContext mProtectedEGLContext;
- EGLSurface mProtectedDummySurface;
+ EGLSurface mProtectedStubSurface;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
GLuint mVpWidth;
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 77b6c0f..8ab2746 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -928,7 +928,7 @@
settings.clip = Rect(4, 4);
settings.clearRegion = Region(Rect(2, 4));
std::vector<const renderengine::LayerSettings*> layers;
- // dummy layer, without bounds should not render anything
+ // fake layer, without bounds should not render anything
renderengine::LayerSettings layer;
layers.push_back(&layer);
invokeDraw(settings, layers, mBuffer);
diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h
new file mode 100644
index 0000000..9eb5483
--- /dev/null
+++ b/libs/ui/include/ui/DisplayId.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <functional>
+#include <string>
+
+namespace android {
+
+// ID of a physical or a virtual display. This class acts as a type safe wrapper around uint64_t.
+struct DisplayId {
+ // TODO(b/162612135) Remove default constructor
+ DisplayId() = default;
+ constexpr DisplayId(const DisplayId&) = default;
+ DisplayId& operator=(const DisplayId&) = default;
+
+ uint64_t value;
+
+protected:
+ explicit constexpr DisplayId(uint64_t id) : value(id) {}
+};
+
+static_assert(sizeof(DisplayId) == sizeof(uint64_t));
+
+inline bool operator==(DisplayId lhs, DisplayId rhs) {
+ return lhs.value == rhs.value;
+}
+
+inline bool operator!=(DisplayId lhs, DisplayId rhs) {
+ return !(lhs == rhs);
+}
+
+inline std::string to_string(DisplayId displayId) {
+ return std::to_string(displayId.value);
+}
+
+// DisplayId of a physical display, such as the internal display or externally connected display.
+struct PhysicalDisplayId : DisplayId {
+ // Flag indicating that the ID is stable across reboots.
+ static constexpr uint64_t FLAG_STABLE = 1ULL << 62;
+
+ // Returns a stable ID based on EDID information.
+ static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId,
+ uint32_t modelHash) {
+ return PhysicalDisplayId(FLAG_STABLE, port, manufacturerId, modelHash);
+ }
+
+ // Returns an unstable ID. If EDID is available using "fromEdid" is preferred.
+ static constexpr PhysicalDisplayId fromPort(uint8_t port) {
+ constexpr uint16_t kManufacturerId = 0;
+ constexpr uint32_t kModelHash = 0;
+ return PhysicalDisplayId(0, port, kManufacturerId, kModelHash);
+ }
+
+ // TODO(b/162612135) Remove default constructor
+ PhysicalDisplayId() = default;
+ explicit constexpr PhysicalDisplayId(uint64_t id) : DisplayId(id) {}
+ explicit constexpr PhysicalDisplayId(DisplayId other) : DisplayId(other.value) {}
+
+ constexpr uint16_t getManufacturerId() const { return static_cast<uint16_t>(value >> 40); }
+
+ constexpr uint8_t getPort() const { return static_cast<uint8_t>(value); }
+
+private:
+ constexpr PhysicalDisplayId(uint64_t flags, uint8_t port, uint16_t manufacturerId,
+ uint32_t modelHash)
+ : DisplayId(flags | (static_cast<uint64_t>(manufacturerId) << 40) |
+ (static_cast<uint64_t>(modelHash) << 8) | port) {}
+};
+
+static_assert(sizeof(PhysicalDisplayId) == sizeof(uint64_t));
+
+} // namespace android
+
+namespace std {
+
+template <>
+struct hash<android::DisplayId> {
+ size_t operator()(android::DisplayId displayId) const {
+ return hash<uint64_t>()(displayId.value);
+ }
+};
+
+template <>
+struct hash<android::PhysicalDisplayId> : hash<android::DisplayId> {};
+
+} // namespace std
diff --git a/libs/ui/include/ui/PhysicalDisplayId.h b/libs/ui/include/ui/PhysicalDisplayId.h
deleted file mode 100644
index 1a345ac..0000000
--- a/libs/ui/include/ui/PhysicalDisplayId.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cinttypes>
-#include <cstdint>
-
-#define ANDROID_PHYSICAL_DISPLAY_ID_FORMAT PRIu64
-
-namespace android {
-
-using PhysicalDisplayId = uint64_t;
-
-constexpr uint8_t getPhysicalDisplayPort(PhysicalDisplayId displayId) {
- return static_cast<uint8_t>(displayId);
-}
-
-} // namespace android
diff --git a/libs/ui/include_vndk/ui/DisplayId.h b/libs/ui/include_vndk/ui/DisplayId.h
new file mode 120000
index 0000000..73c9fe8
--- /dev/null
+++ b/libs/ui/include_vndk/ui/DisplayId.h
@@ -0,0 +1 @@
+../../include/ui/DisplayId.h
\ No newline at end of file
diff --git a/libs/ui/include_vndk/ui/PhysicalDisplayId.h b/libs/ui/include_vndk/ui/PhysicalDisplayId.h
deleted file mode 120000
index 6e3fb1e..0000000
--- a/libs/ui/include_vndk/ui/PhysicalDisplayId.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/ui/PhysicalDisplayId.h
\ No newline at end of file
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 8cc7081..fab1097 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -108,7 +108,7 @@
void ConnectProducer() {
IGraphicBufferProducer::QueueBufferOutput output;
// Can connect the first time.
- ASSERT_EQ(OK, mProducer->connect(kDummyListener, kTestApi,
+ ASSERT_EQ(OK, mProducer->connect(kStubListener, kTestApi,
kTestControlledByApp, &output));
}
@@ -140,7 +140,7 @@
return QueueBufferInputBuilder().build();
}
- const sp<IProducerListener> kDummyListener{new DummyProducerListener};
+ const sp<IProducerListener> kStubListener{new StubProducerListener};
sp<BufferHubProducer> mProducer;
sp<Surface> mSurface;
@@ -150,11 +150,11 @@
IGraphicBufferProducer::QueueBufferOutput output;
// NULL output returns BAD_VALUE
- EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
+ EXPECT_EQ(BAD_VALUE, mProducer->connect(kStubListener, kTestApi,
kTestControlledByApp, nullptr));
// Invalid API returns bad value
- EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApiInvalid,
+ EXPECT_EQ(BAD_VALUE, mProducer->connect(kStubListener, kTestApiInvalid,
kTestControlledByApp, &output));
}
@@ -163,7 +163,7 @@
// Can't connect when there is already a producer connected.
IGraphicBufferProducer::QueueBufferOutput output;
- EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
+ EXPECT_EQ(BAD_VALUE, mProducer->connect(kStubListener, kTestApi,
kTestControlledByApp, &output));
}
@@ -554,18 +554,18 @@
ProducerQueueParcelable producer_parcelable;
EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
- // Create a valid dummy producer parcelable.
- auto dummy_channel_parcelable =
+ // Create a valid fake producer parcelable.
+ auto fake_channel_parcelable =
std::make_unique<pdx::default_transport::ChannelParcelable>(
LocalHandle(0), LocalHandle(0), LocalHandle(0));
- EXPECT_TRUE(dummy_channel_parcelable->IsValid());
- ProducerQueueParcelable dummy_producer_parcelable(
- std::move(dummy_channel_parcelable));
- EXPECT_TRUE(dummy_producer_parcelable.IsValid());
+ EXPECT_TRUE(fake_channel_parcelable->IsValid());
+ ProducerQueueParcelable fake_producer_parcelable(
+ std::move(fake_channel_parcelable));
+ EXPECT_TRUE(fake_producer_parcelable.IsValid());
// Disconnect producer can be taken out, but only to an invalid parcelable.
ASSERT_EQ(mProducer->disconnect(kTestApi), OK);
- EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
+ EXPECT_EQ(mProducer->TakeAsParcelable(&fake_producer_parcelable), BAD_VALUE);
EXPECT_FALSE(producer_parcelable.IsValid());
EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), OK);
EXPECT_TRUE(producer_parcelable.IsValid());
@@ -583,7 +583,7 @@
// But connect to API will fail.
IGraphicBufferProducer::QueueBufferOutput output;
- EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
+ EXPECT_EQ(mProducer->connect(kStubListener, kTestApi, kTestControlledByApp,
&output),
BAD_VALUE);
@@ -592,8 +592,8 @@
sp<BufferHubProducer> new_producer =
BufferHubProducer::Create(std::move(producer_parcelable));
ASSERT_TRUE(new_producer != nullptr);
- EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
- kTestControlledByApp, &output),
+ EXPECT_EQ(new_producer->connect(kStubListener, kTestApi, kTestControlledByApp,
+ &output),
OK);
}
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index 7b3717e..07e2121 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -308,14 +308,6 @@
class DvrDisplayManagerTest : public Test {
protected:
void SetUp() override {
- // dvr display manager test doesn't apply to standalone vr devices because
- // tests cannot create display manager client on these devices.
- if (property_get_bool("ro.boot.vr", false)) {
- GTEST_SKIP()
- << "All tests in DvrDisplayManagerTest test case are skipped "
- "because the device boot to VR.";
- }
-
int ret;
DvrDisplayManager* display_manager;
DvrSurfaceState* surface_state;
diff --git a/libs/vr/libpdx/encoder_performance_test.cpp b/libs/vr/libpdx/encoder_performance_test.cpp
index b7d94b3..7b477c4 100644
--- a/libs/vr/libpdx/encoder_performance_test.cpp
+++ b/libs/vr/libpdx/encoder_performance_test.cpp
@@ -158,12 +158,12 @@
size_t iterations,
ResetFunc* write_reset,
void* reset_data, size_t data_size) {
- std::vector<uint8_t> dummy_data(data_size);
+ std::vector<uint8_t> fake_data(data_size);
auto start = std::chrono::high_resolution_clock::now();
for (size_t i = 0; i < iterations; i++) {
write_reset(reset_data);
- memcpy(writer->GetNextWriteBufferSection(dummy_data.size()),
- dummy_data.data(), dummy_data.size());
+ memcpy(writer->GetNextWriteBufferSection(fake_data.size()),
+ fake_data.data(), fake_data.size());
}
auto stop = std::chrono::high_resolution_clock::now();
return stop - start;
@@ -177,17 +177,17 @@
MessageReader* reader, MessageWriter* writer, size_t iterations,
ResetFunc* read_reset, ResetFunc* write_reset, void* reset_data,
size_t data_size) {
- std::vector<uint8_t> dummy_data(data_size);
+ std::vector<uint8_t> fake_data(data_size);
write_reset(reset_data);
- memcpy(writer->GetNextWriteBufferSection(dummy_data.size()),
- dummy_data.data(), dummy_data.size());
+ memcpy(writer->GetNextWriteBufferSection(fake_data.size()), fake_data.data(),
+ fake_data.size());
auto start = std::chrono::high_resolution_clock::now();
for (size_t i = 0; i < iterations; i++) {
read_reset(reset_data);
auto section = reader->GetNextReadBufferSection();
- memcpy(dummy_data.data(), section.first, dummy_data.size());
+ memcpy(fake_data.data(), section.first, fake_data.size());
reader->ConsumeReadBufferSectionData(
- AdvancePointer(section.first, dummy_data.size()));
+ AdvancePointer(section.first, fake_data.size()));
}
auto stop = std::chrono::high_resolution_clock::now();
return stop - start;
diff --git a/libs/vr/libpdx/private/pdx/rpc/macros.h b/libs/vr/libpdx/private/pdx/rpc/macros.h
index aeae9d3..99325b5 100644
--- a/libs/vr/libpdx/private/pdx/rpc/macros.h
+++ b/libs/vr/libpdx/private/pdx/rpc/macros.h
@@ -28,7 +28,7 @@
// Clears any remaining contents wrapped in parentheses.
#define _PDX_CLEAR(...)
-// Introduces a first dummy argument and _PDX_CLEAR as second argument.
+// Introduces a first stub argument and _PDX_CLEAR as second argument.
#define _PDX_CLEAR_IF_LAST() _, _PDX_CLEAR
// Returns the first argument of a list.
@@ -45,7 +45,7 @@
// Returns next_func if the next element is not (), or _PDX_CLEAR
// otherwise.
//
-// _PDX_CLEAR_IF_LAST inserts an extra first dummy argument if peek is ().
+// _PDX_CLEAR_IF_LAST inserts an extra first stub argument if peek is ().
#define _PDX_NEXT_FUNC(next_element, next_func) \
_PDX_EXPAND_NEXT_FUNC(_PDX_CLEAR_IF_LAST next_element, next_func)
diff --git a/libs/vr/libpdx/service_dispatcher.cpp b/libs/vr/libpdx/service_dispatcher.cpp
index b112fa3..ba0d69c 100644
--- a/libs/vr/libpdx/service_dispatcher.cpp
+++ b/libs/vr/libpdx/service_dispatcher.cpp
@@ -92,9 +92,9 @@
if (thread_count_ > 0)
return -EBUSY;
- epoll_event dummy; // See BUGS in man 2 epoll_ctl.
+ epoll_event ee; // See BUGS in man 2 epoll_ctl.
if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, service->endpoint()->epoll_fd(),
- &dummy) < 0) {
+ &ee) < 0) {
ALOGE("Failed to remove service from dispatcher because: %s\n",
strerror(errno));
return -errno;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 9bc70ea..810eb19 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -334,8 +334,8 @@
int channel_fd = iter->second.data_fd.Get();
Status<void> status;
- epoll_event dummy; // See BUGS in man 2 epoll_ctl.
- if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_fd, &dummy) < 0) {
+ epoll_event ee; // See BUGS in man 2 epoll_ctl.
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_fd, &ee) < 0) {
status.SetError(errno);
ALOGE(
"Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
index 1cf5f17..0d5eb80 100644
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
@@ -68,8 +68,8 @@
ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd);
std::lock_guard<std::mutex> lock(lock_);
- epoll_event dummy; // See BUGS in man 2 epoll_ctl.
- if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &dummy) < 0) {
+ epoll_event ee; // See BUGS in man 2 epoll_ctl.
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &ee) < 0) {
const int error = errno;
ALOGE("Failed to remove fd from epoll set because: %s", strerror(error));
return pdx::ErrorStatus(error);
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index b771538..70f303b 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -47,7 +47,6 @@
namespace {
const char kDvrPerformanceProperty[] = "sys.dvr.performance";
-const char kDvrStandaloneProperty[] = "ro.boot.vr";
const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
@@ -159,8 +158,6 @@
return false;
}
- is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
-
request_display_callback_ = request_display_callback;
primary_display_ = GetDisplayParams(composer, primary_display_id, true);
@@ -206,8 +203,6 @@
return;
boot_finished_ = true;
post_thread_wait_.notify_one();
- if (is_standalone_device_)
- request_display_callback_(true);
}
// Update the post thread quiescent state based on idle and suspended inputs.
@@ -267,17 +262,11 @@
layers_.clear();
// Phones create a new composer client on resume and destroy it on pause.
- // Standalones only create the composer client once and then use SetPowerMode
- // to control the screen on pause/resume.
- if (!is_standalone_device_) {
- if (composer_callback_ != nullptr) {
- composer_callback_->SetVsyncService(nullptr);
- composer_callback_ = nullptr;
- }
- composer_.reset(nullptr);
- } else {
- EnableDisplay(*target_display_, false);
+ if (composer_callback_ != nullptr) {
+ composer_callback_->SetVsyncService(nullptr);
+ composer_callback_ = nullptr;
}
+ composer_.reset(nullptr);
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
@@ -588,7 +577,7 @@
surfaces_changed_ = true;
}
- if (request_display_callback_ && !is_standalone_device_)
+ if (request_display_callback_)
request_display_callback_(!display_idle);
// Set idle state based on whether there are any surfaces to handle.
@@ -773,28 +762,6 @@
VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets();
- if (is_standalone_device_) {
- // First, wait until boot finishes.
- std::unique_lock<std::mutex> lock(post_thread_mutex_);
- if (PostThreadCondWait(lock, -1, [this] { return boot_finished_; })) {
- return;
- }
-
- // Then, wait until we're either leaving the quiescent state, or the boot
- // finished display off timeout expires.
- if (PostThreadCondWait(lock, kBootFinishedDisplayOffTimeoutSec,
- [this] { return !post_thread_quiescent_; })) {
- return;
- }
-
- LOG_ALWAYS_FATAL_IF(post_thread_state_ & PostThreadState::Suspended,
- "Vr flinger should own the display by now.");
- post_thread_resumed_ = true;
- post_thread_ready_.notify_all();
- if (!composer_)
- CreateComposer();
- }
-
while (1) {
ATRACE_NAME("HardwareComposer::PostThread");
diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
index efd6d1d..ac44f74 100644
--- a/libs/vr/libvrflinger/tests/vrflinger_test.cpp
+++ b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
@@ -43,9 +43,6 @@
// completed.
constexpr auto kVrFlingerSwitchPollInterval = std::chrono::milliseconds(50);
-// How long to wait for a device that boots to VR to have vr flinger ready.
-constexpr auto kBootVrFlingerWaitTimeout = std::chrono::seconds(30);
-
// A Binder connection to surface flinger.
class SurfaceFlingerConnection {
public:
@@ -153,11 +150,6 @@
return;
}
- // This test doesn't apply to standalone vr devices.
- if (property_get_bool("ro.boot.vr", false)) {
- return;
- }
-
auto surface_flinger_connection = SurfaceFlingerConnection::Create();
ASSERT_NE(surface_flinger_connection, nullptr);
@@ -230,31 +222,5 @@
SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess);
}
-// This test runs only on devices that boot to vr. Such a device should boot to
-// a state where vr flinger is running, and the test verifies this after a
-// delay.
-TEST(BootVrFlingerTest, BootsToVrFlinger) {
- // Exit if we are not running on a device that boots to vr.
- if (!property_get_bool("ro.boot.vr", false)) {
- return;
- }
-
- auto surface_flinger_connection = SurfaceFlingerConnection::Create();
- ASSERT_NE(surface_flinger_connection, nullptr);
-
- // Verify that vr flinger is enabled.
- ASSERT_TRUE(surface_flinger_connection->IsAlive());
- auto vr_flinger_active = surface_flinger_connection->IsVrFlingerActive();
- ASSERT_TRUE(vr_flinger_active.has_value());
-
- bool active_value = vr_flinger_active.value();
- if (!active_value) {
- // Try again, but delay up to 30 seconds.
- ASSERT_EQ(surface_flinger_connection->WaitForVrFlingerTimed(true,
- kVrFlingerSwitchPollInterval, kBootVrFlingerWaitTimeout),
- SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess);
- }
-}
-
} // namespace dvr
} // namespace android
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 74fb019..a27c09f 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -78,12 +78,12 @@
return;
}
- std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false));
- CacheEntry dummyEntry(dummyKey, nullptr);
+ std::shared_ptr<Blob> cacheKey(new Blob(key, keySize, false));
+ CacheEntry cacheEntry(cacheKey, nullptr);
while (true) {
- auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry);
- if (index == mCacheEntries.end() || dummyEntry < *index) {
+ auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), cacheEntry);
+ if (index == mCacheEntries.end() || cacheEntry < *index) {
// Create a new cache entry.
std::shared_ptr<Blob> keyBlob(new Blob(key, keySize, true));
std::shared_ptr<Blob> valueBlob(new Blob(value, valueSize, true));
@@ -138,10 +138,10 @@
keySize, mMaxKeySize);
return 0;
}
- std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false));
- CacheEntry dummyEntry(dummyKey, nullptr);
- auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry);
- if (index == mCacheEntries.end() || dummyEntry < *index) {
+ std::shared_ptr<Blob> cacheKey(new Blob(key, keySize, false));
+ CacheEntry cacheEntry(cacheKey, nullptr);
+ auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), cacheEntry);
+ if (index == mCacheEntries.end() || cacheEntry < *index) {
ALOGV("get: no cache entry found for key of size %zu", keySize);
return 0;
}
diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp
index 3284778..751f3be 100644
--- a/opengl/libs/EGL/FileBlobCache.cpp
+++ b/opengl/libs/EGL/FileBlobCache.cpp
@@ -70,7 +70,7 @@
return;
}
- // Sanity check the size before trying to mmap it.
+ // Check the size before trying to mmap it.
size_t fileSize = statBuf.st_size;
if (fileSize > mMaxTotalSize * 2) {
ALOGE("cache file is too large: %#" PRIx64,
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 510226d..bbd786d 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -138,7 +138,7 @@
};
EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -148,7 +148,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -258,7 +258,7 @@
EXPECT_EQ(components[2], 8);
EXPECT_EQ(components[3], 8);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -268,7 +268,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
EGLint winAttrs[] = {
@@ -306,7 +306,7 @@
get8BitConfig(config);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -316,7 +316,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
EGLint winAttrs[] = {
@@ -398,7 +398,7 @@
EXPECT_EQ(components[2], 10);
EXPECT_EQ(components[3], 2);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -408,7 +408,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
EGLint winAttrs[] = {
@@ -570,7 +570,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -580,7 +580,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -622,7 +622,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -632,7 +632,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
std::vector<EGLint> winAttrs;
@@ -705,7 +705,7 @@
EXPECT_GE(components[2], 16);
EXPECT_GE(components[3], 16);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -714,7 +714,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -734,7 +734,7 @@
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -809,7 +809,7 @@
EXPECT_EQ(components[2], 10);
EXPECT_EQ(components[3], 2);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -819,7 +819,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -835,7 +835,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -845,7 +845,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -882,7 +882,7 @@
ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(1, numConfigs);
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -892,7 +892,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -913,7 +913,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -923,7 +923,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
@@ -953,7 +953,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct DummyConsumer : public BnConsumerListener {
+ struct MockConsumer : public BnConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -963,7 +963,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->consumerConnect(new DummyConsumer, false);
+ consumer->consumerConnect(new MockConsumer, false);
sp<Surface> mSTC = new Surface(producer);
sp<ANativeWindow> mANW = mSTC;
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 9efd38f..7fd9c3a 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -17,7 +17,7 @@
mkdir out
-# Create dummy Java files for Android APIs that are used by the code we generate.
+# Create stub Java files for Android APIs that are used by the code we generate.
# This allows us to test the generated code without building the rest of Android.
mkdir -p out/javax/microedition/khronos/opengles
diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp
index 4767406..321bb83 100644
--- a/services/automotive/display/AutomotiveDisplayProxyService.cpp
+++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp
@@ -34,7 +34,7 @@
sp<IBinder> displayToken = nullptr;
sp<SurfaceControl> surfaceControl = nullptr;
if (it == mDisplays.end()) {
- displayToken = SurfaceComposerClient::getPhysicalDisplayToken(id);
+ displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id));
if (displayToken == nullptr) {
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
return nullptr;
@@ -145,7 +145,7 @@
auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
ids.resize(displayIds.size());
for (auto i = 0; i < displayIds.size(); ++i) {
- ids[i] = displayIds[i];
+ ids[i] = displayIds[i].value;
}
_cb(ids);
@@ -157,7 +157,7 @@
HwDisplayConfig activeConfig;
HwDisplayState activeState;
- auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(id);
+ auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id));
if (displayToken == nullptr) {
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
} else {
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 18c819f..52d5d4f 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -75,11 +75,23 @@
}
void GpuService::setUpdatableDriverPath(const std::string& driverPath) {
- developerDriverPath = driverPath;
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+
+ // only system_server is allowed to set updatable driver path
+ if (uid != AID_SYSTEM) {
+ ALOGE("Permission Denial: can't set updatable driver path from pid=%d, uid=%d\n", pid, uid);
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mLock);
+ mDeveloperDriverPath = driverPath;
}
std::string GpuService::getUpdatableDriverPath() {
- return developerDriverPath;
+ std::lock_guard<std::mutex> lock(mLock);
+ return mDeveloperDriverPath;
}
status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 43faa3e..409084b 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -79,7 +79,8 @@
std::shared_ptr<GpuMem> mGpuMem;
std::unique_ptr<GpuStats> mGpuStats;
std::unique_ptr<GpuMemTracer> mGpuMemTracer;
- std::string developerDriverPath;
+ std::mutex mLock;
+ std::string mDeveloperDriverPath;
};
} // namespace android
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 231d068..220952d 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -291,24 +291,27 @@
if (data) {
for (const auto& ele : mAppStats) {
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::GPU_STATS_APP_INFO);
- AStatsEvent_writeString(event, ele.second.appPackageName.c_str());
- AStatsEvent_writeInt64(event, ele.second.driverVersionCode);
+ std::string glDriverBytes = int64VectorToProtoByteString(
+ ele.second.glDriverLoadingTime);
+ std::string vkDriverBytes = int64VectorToProtoByteString(
+ ele.second.vkDriverLoadingTime);
+ std::string angleDriverBytes = int64VectorToProtoByteString(
+ ele.second.angleDriverLoadingTime);
- std::string bytes = int64VectorToProtoByteString(ele.second.glDriverLoadingTime);
- AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
-
- bytes = int64VectorToProtoByteString(ele.second.vkDriverLoadingTime);
- AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
-
- bytes = int64VectorToProtoByteString(ele.second.angleDriverLoadingTime);
- AStatsEvent_writeByteArray(event, (const uint8_t*)bytes.c_str(), bytes.length());
-
- AStatsEvent_writeBool(event, ele.second.cpuVulkanInUse);
- AStatsEvent_writeBool(event, ele.second.falsePrerotation);
- AStatsEvent_writeBool(event, ele.second.gles1InUse);
- AStatsEvent_build(event);
+ android::util::addAStatsEvent(
+ data,
+ android::util::GPU_STATS_APP_INFO,
+ ele.second.appPackageName.c_str(),
+ ele.second.driverVersionCode,
+ android::util::BytesField(glDriverBytes.c_str(),
+ glDriverBytes.length()),
+ android::util::BytesField(vkDriverBytes.c_str(),
+ vkDriverBytes.length()),
+ android::util::BytesField(angleDriverBytes.c_str(),
+ angleDriverBytes.length()),
+ ele.second.cpuVulkanInUse,
+ ele.second.falsePrerotation,
+ ele.second.gles1InUse);
}
}
@@ -326,22 +329,22 @@
if (data) {
for (const auto& ele : mGlobalStats) {
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::GPU_STATS_GLOBAL_INFO);
- AStatsEvent_writeString(event, ele.second.driverPackageName.c_str());
- AStatsEvent_writeString(event, ele.second.driverVersionName.c_str());
- AStatsEvent_writeInt64(event, ele.second.driverVersionCode);
- AStatsEvent_writeInt64(event, ele.second.driverBuildTime);
- AStatsEvent_writeInt64(event, ele.second.glLoadingCount);
- AStatsEvent_writeInt64(event, ele.second.glLoadingFailureCount);
- AStatsEvent_writeInt64(event, ele.second.vkLoadingCount);
- AStatsEvent_writeInt64(event, ele.second.vkLoadingFailureCount);
- AStatsEvent_writeInt32(event, ele.second.vulkanVersion);
- AStatsEvent_writeInt32(event, ele.second.cpuVulkanVersion);
- AStatsEvent_writeInt32(event, ele.second.glesVersion);
- AStatsEvent_writeInt64(event, ele.second.angleLoadingCount);
- AStatsEvent_writeInt64(event, ele.second.angleLoadingFailureCount);
- AStatsEvent_build(event);
+ android::util::addAStatsEvent(
+ data,
+ android::util::GPU_STATS_GLOBAL_INFO,
+ ele.second.driverPackageName.c_str(),
+ ele.second.driverVersionName.c_str(),
+ ele.second.driverVersionCode,
+ ele.second.driverBuildTime,
+ ele.second.glLoadingCount,
+ ele.second.glLoadingFailureCount,
+ ele.second.vkLoadingCount,
+ ele.second.vkLoadingFailureCount,
+ ele.second.vulkanVersion,
+ ele.second.cpuVulkanVersion,
+ ele.second.glesVersion,
+ ele.second.angleLoadingCount,
+ ele.second.angleLoadingFailureCount);
}
}
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 4e4af7e..b31980b 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -47,8 +47,8 @@
private:
void notifyConfigurationChanged(nsecs_t) override {}
- std::chrono::nanoseconds notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&,
- const std::string& name) override {
+ std::chrono::nanoseconds notifyAnr(const std::shared_ptr<InputApplicationHandle>&,
+ const sp<IBinder>&, const std::string& name) override {
ALOGE("The window is not responding : %s", name.c_str());
return 0s;
}
@@ -94,7 +94,8 @@
virtual ~FakeApplicationHandle() {}
virtual bool updateInfo() {
- mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo.dispatchingTimeoutMillis =
+ std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
return true;
}
};
@@ -148,7 +149,7 @@
static const int32_t WIDTH = 200;
static const int32_t HEIGHT = 200;
- FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+ FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
const sp<InputDispatcher>& dispatcher, const std::string name)
: FakeInputReceiver(dispatcher, name), mFrame(Rect(0, 0, WIDTH, HEIGHT)) {
mDispatcher->registerInputChannel(mServerChannel);
@@ -246,7 +247,7 @@
dispatcher->start();
// Create a window that will receive motion events
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = new FakeWindowHandle(application, dispatcher, "Fake Window");
dispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -282,7 +283,7 @@
dispatcher->start();
// Create a window that will receive motion events
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = new FakeWindowHandle(application, dispatcher, "Fake Window");
dispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 26a1644..ded74ba 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -117,10 +117,12 @@
// --- FocusEntry ---
// Focus notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries
-FocusEntry::FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus)
+FocusEntry::FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus,
+ std::string_view reason)
: EventEntry(id, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER),
connectionToken(connectionToken),
- hasFocus(hasFocus) {}
+ hasFocus(hasFocus),
+ reason(reason) {}
FocusEntry::~FocusEntry() {}
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index e5b36f4..5fd772e 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -112,8 +112,10 @@
struct FocusEntry : EventEntry {
sp<IBinder> connectionToken;
bool hasFocus;
+ std::string_view reason;
- FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus);
+ FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus,
+ std::string_view reason);
virtual void appendDescription(std::string& msg) const;
protected:
@@ -254,7 +256,7 @@
sp<Connection> connection;
nsecs_t eventTime;
KeyEntry* keyEntry;
- sp<InputApplicationHandle> inputApplicationHandle;
+ std::shared_ptr<InputApplicationHandle> inputApplicationHandle;
std::string reason;
int32_t userActivityEventType;
uint32_t seq;
diff --git a/services/inputflinger/dispatcher/EventLogTags.logtags b/services/inputflinger/dispatcher/EventLogTags.logtags
index 9c0f80e..2836467 100644
--- a/services/inputflinger/dispatcher/EventLogTags.logtags
+++ b/services/inputflinger/dispatcher/EventLogTags.logtags
@@ -36,7 +36,7 @@
# 62000 - 62199 reserved for inputflinger
62000 input_interaction (windows|4)
-62001 input_focus (window|3)
+62001 input_focus (window|3),(reason|3)
# NOTE - the range 1000000-2000000 is reserved for partners and others who
# want to define their own log tags without conflicting with the core platform.
\ No newline at end of file
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 5a4143a..5ba5ad8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -47,6 +47,7 @@
#include <android-base/chrono_utils.h>
#include <android-base/stringprintf.h>
+#include <android/os/IInputConstants.h>
#include <binder/Binder.h>
#include <input/InputDevice.h>
#include <input/InputWindow.h>
@@ -80,7 +81,8 @@
// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
-constexpr std::chrono::nanoseconds DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5s;
+constexpr std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT =
+ std::chrono::milliseconds(android::os::IInputConstants::DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
// Amount of time to allow for all pending events to be processed when an app switch
// key is on the way. This is used to preempt input dispatch and drop input events
@@ -496,7 +498,7 @@
if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
if (currentTime >= *mNoFocusedWindowTimeoutTime) {
onAnrLocked(mAwaitedFocusedApplication);
- mAwaitedFocusedApplication.clear();
+ mAwaitedFocusedApplication.reset();
return LONG_LONG_MIN;
} else {
// Keep waiting
@@ -525,12 +527,12 @@
return LONG_LONG_MIN;
}
-nsecs_t InputDispatcher::getDispatchingTimeoutLocked(const sp<IBinder>& token) {
+std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked(const sp<IBinder>& token) {
sp<InputWindowHandle> window = getWindowHandleLocked(token);
if (window != nullptr) {
- return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT).count();
+ return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
}
- return DEFAULT_INPUT_DISPATCHING_TIMEOUT.count();
+ return DEFAULT_INPUT_DISPATCHING_TIMEOUT;
}
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
@@ -1076,7 +1078,8 @@
return true;
}
-void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) {
+void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus,
+ std::string_view reason) {
if (mPendingEvent != nullptr) {
// Move the pending event to the front of the queue. This will give the chance
// for the pending event to get dispatched to the newly focused window
@@ -1085,7 +1088,7 @@
}
FocusEntry* focusEntry =
- new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus);
+ new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus, reason);
// This event should go to the front of the queue, but behind all other focus events
// Find the last focus event, and insert right after it
@@ -1108,7 +1111,8 @@
entry->dispatchInProgress = true;
std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") +
channel->getName();
- android_log_event_list(LOGTAG_INPUT_FOCUS) << message << LOG_ID_EVENTS;
+ std::string reason = std::string("reason=").append(entry->reason);
+ android_log_event_list(LOGTAG_INPUT_FOCUS) << message << reason << LOG_ID_EVENTS;
dispatchEventLocked(currentTime, entry, {target});
}
@@ -1389,7 +1393,7 @@
// Reset input target wait timeout.
mNoFocusedWindowTimeoutTime = std::nullopt;
- mAwaitedFocusedApplication.clear();
+ mAwaitedFocusedApplication.reset();
}
/**
@@ -1433,7 +1437,9 @@
ALOGD("Waiting to send key to %s because there are unprocessed events that may cause "
"focus to change",
focusedWindowName);
- mKeyIsWaitingForEventsTimeout = currentTime + KEY_WAITING_FOR_EVENTS_TIMEOUT.count();
+ mKeyIsWaitingForEventsTimeout = currentTime +
+ std::chrono::duration_cast<std::chrono::nanoseconds>(KEY_WAITING_FOR_EVENTS_TIMEOUT)
+ .count();
return true;
}
@@ -1459,7 +1465,7 @@
int32_t displayId = getTargetDisplayId(entry);
sp<InputWindowHandle> focusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
- sp<InputApplicationHandle> focusedApplicationHandle =
+ std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
// If there is no currently focused window and no focused application
@@ -1687,15 +1693,11 @@
newTouchedWindowHandle = nullptr;
}
+ // Ensure the window has a connection and the connection is responsive
if (newTouchedWindowHandle != nullptr) {
- sp<Connection> connection = getConnectionLocked(newTouchedWindowHandle->getToken());
- if (connection == nullptr) {
- ALOGI("Could not find connection for %s",
- newTouchedWindowHandle->getName().c_str());
- newTouchedWindowHandle = nullptr;
- } else if (!connection->responsive) {
- // don't send the new touch to an unresponsive window
- ALOGW("Unresponsive window %s will not get the new gesture at %" PRIu64,
+ const bool isResponsive = hasResponsiveConnectionLocked(*newTouchedWindowHandle);
+ if (!isResponsive) {
+ ALOGW("%s will not receive the new gesture at %" PRIu64,
newTouchedWindowHandle->getName().c_str(), entry.eventTime);
newTouchedWindowHandle = nullptr;
}
@@ -2149,7 +2151,7 @@
}
std::string InputDispatcher::getApplicationWindowLabel(
- const sp<InputApplicationHandle>& applicationHandle,
+ const std::shared_ptr<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle) {
if (applicationHandle != nullptr) {
if (windowHandle != nullptr) {
@@ -2549,9 +2551,9 @@
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
- const nsecs_t timeout =
+ const std::chrono::nanoseconds timeout =
getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
- dispatchEntry->timeoutTime = currentTime + timeout;
+ dispatchEntry->timeoutTime = currentTime + timeout.count();
// Publish the event.
status_t status;
@@ -3678,6 +3680,29 @@
return false;
}
+bool InputDispatcher::hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const {
+ sp<Connection> connection = getConnectionLocked(windowHandle.getToken());
+ const bool noInputChannel =
+ windowHandle.getInfo()->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ if (connection != nullptr && noInputChannel) {
+ ALOGW("%s has feature NO_INPUT_CHANNEL, but it matched to connection %s",
+ windowHandle.getName().c_str(), connection->inputChannel->getName().c_str());
+ return false;
+ }
+
+ if (connection == nullptr) {
+ if (!noInputChannel) {
+ ALOGI("Could not find connection for %s", windowHandle.getName().c_str());
+ }
+ return false;
+ }
+ if (!connection->responsive) {
+ ALOGW("Window %s is not responsive", windowHandle.getName().c_str());
+ return false;
+ }
+ return true;
+}
+
std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked(
const sp<IBinder>& token) const {
size_t count = mInputChannelsByToken.count(token);
@@ -3773,6 +3798,17 @@
ALOGD("setInputWindows displayId=%" PRId32 " %s", displayId, windowList.c_str());
}
+ // Ensure all tokens are null if the window has feature NO_INPUT_CHANNEL
+ for (const sp<InputWindowHandle>& window : inputWindowHandles) {
+ const bool noInputWindow =
+ window->getInfo()->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ if (noInputWindow && window->getToken() != nullptr) {
+ ALOGE("%s has feature NO_INPUT_WINDOW, but a non-null token. Clearing",
+ window->getName().c_str());
+ window->releaseChannel();
+ }
+ }
+
// Copy old handles for release if they are no longer present.
const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
@@ -3799,33 +3835,8 @@
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) {
- if (oldFocusedWindowHandle != nullptr) {
- if (DEBUG_FOCUS) {
- ALOGD("Focus left window: %s in display %" PRId32,
- oldFocusedWindowHandle->getName().c_str(), displayId);
- }
- std::shared_ptr<InputChannel> focusedInputChannel =
- getInputChannelLocked(oldFocusedWindowHandle->getToken());
- if (focusedInputChannel != nullptr) {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "focus left window");
- synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
- enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/);
- }
- mFocusedWindowHandlesByDisplay.erase(displayId);
- }
- if (newFocusedWindowHandle != nullptr) {
- if (DEBUG_FOCUS) {
- ALOGD("Focus entered window: %s in display %" PRId32,
- newFocusedWindowHandle->getName().c_str(), displayId);
- }
- mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
- enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/);
- }
-
- if (mFocusedDisplayId == displayId) {
- onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
- }
+ onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle, displayId,
+ "setInputWindowsLocked");
}
std::unordered_map<int32_t, TouchState>::iterator stateIt =
@@ -3868,30 +3879,36 @@
}
void InputDispatcher::setFocusedApplication(
- int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
+ int32_t displayId, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
if (DEBUG_FOCUS) {
ALOGD("setFocusedApplication displayId=%" PRId32 " %s", displayId,
inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
}
- { // acquire lock
+ if (inputApplicationHandle != nullptr &&
+ inputApplicationHandle->getApplicationToken() != nullptr) {
+ // acquire lock
std::scoped_lock _l(mLock);
- sp<InputApplicationHandle> oldFocusedApplicationHandle =
+ std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
- if (oldFocusedApplicationHandle == mAwaitedFocusedApplication &&
- inputApplicationHandle != oldFocusedApplicationHandle) {
- resetNoFocusedWindowTimeoutLocked();
+ // If oldFocusedApplicationHandle already exists
+ if (oldFocusedApplicationHandle != nullptr) {
+ // If a new focused application handle is different from the old one and
+ // old focus application info is awaited focused application info.
+ if (*oldFocusedApplicationHandle != *inputApplicationHandle &&
+ mAwaitedFocusedApplication != nullptr &&
+ *oldFocusedApplicationHandle == *mAwaitedFocusedApplication) {
+ resetNoFocusedWindowTimeoutLocked();
+ }
+ // Erase the old application from container first
+ mFocusedApplicationHandlesByDisplay.erase(displayId);
+ // Should already get freed after removed from container but just double check.
+ oldFocusedApplicationHandle.reset();
}
- if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
- if (oldFocusedApplicationHandle != inputApplicationHandle) {
- mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
- }
- } else if (oldFocusedApplicationHandle != nullptr) {
- oldFocusedApplicationHandle.clear();
- mFocusedApplicationHandlesByDisplay.erase(displayId);
- }
+ // Set the new application handle.
+ mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
@@ -3933,7 +3950,7 @@
// Sanity check
sp<InputWindowHandle> newFocusedWindowHandle =
getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
- onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
+ notifyFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
if (newFocusedWindowHandle == nullptr) {
ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
@@ -4138,12 +4155,12 @@
dump += StringPrintf(INDENT "FocusedApplications:\n");
for (auto& it : mFocusedApplicationHandlesByDisplay) {
const int32_t displayId = it.first;
- const sp<InputApplicationHandle>& applicationHandle = it.second;
- const int64_t timeoutMillis = millis(
- applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT));
+ const std::shared_ptr<InputApplicationHandle>& applicationHandle = it.second;
+ const std::chrono::duration timeout =
+ applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
dump += StringPrintf(INDENT2 "displayId=%" PRId32
", name='%s', dispatchingTimeout=%" PRId64 "ms\n",
- displayId, applicationHandle->getName().c_str(), timeoutMillis);
+ displayId, applicationHandle->getName().c_str(), millis(timeout));
}
} else {
dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
@@ -4606,8 +4623,8 @@
postCommandLocked(std::move(commandEntry));
}
-void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
- const sp<InputWindowHandle>& newFocus) {
+void InputDispatcher::notifyFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+ const sp<InputWindowHandle>& newFocus) {
sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
@@ -4652,7 +4669,7 @@
postCommandLocked(std::move(commandEntry));
}
-void InputDispatcher::onAnrLocked(const sp<InputApplicationHandle>& application) {
+void InputDispatcher::onAnrLocked(const std::shared_ptr<InputApplicationHandle>& application) {
std::string reason = android::base::StringPrintf("%s does not have a focused window",
application->getName().c_str());
@@ -4672,8 +4689,8 @@
updateLastAnrStateLocked(windowLabel, reason);
}
-void InputDispatcher::updateLastAnrStateLocked(const sp<InputApplicationHandle>& application,
- const std::string& reason) {
+void InputDispatcher::updateLastAnrStateLocked(
+ const std::shared_ptr<InputApplicationHandle>& application, const std::string& reason) {
const std::string windowLabel = getApplicationWindowLabel(application, nullptr);
updateLastAnrStateLocked(windowLabel, reason);
}
@@ -4744,9 +4761,9 @@
}
}
-void InputDispatcher::extendAnrTimeoutsLocked(const sp<InputApplicationHandle>& application,
- const sp<IBinder>& connectionToken,
- std::chrono::nanoseconds timeoutExtension) {
+void InputDispatcher::extendAnrTimeoutsLocked(
+ const std::shared_ptr<InputApplicationHandle>& application,
+ const sp<IBinder>& connectionToken, std::chrono::nanoseconds timeoutExtension) {
sp<Connection> connection = getConnectionLocked(connectionToken);
if (connection == nullptr) {
if (mNoFocusedWindowTimeoutTime.has_value() && application != nullptr) {
@@ -5186,5 +5203,37 @@
* when requesting the focus change. This determines which request gets
* precedence if there is a focus change request from another source such as pointer down.
*/
-void InputDispatcher::setFocusedWindow(const FocusRequest&) {}
+void InputDispatcher::setFocusedWindow(const FocusRequest& request) {}
+
+void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocusedWindowHandle,
+ const sp<InputWindowHandle>& newFocusedWindowHandle,
+ int32_t displayId, std::string_view reason) {
+ if (oldFocusedWindowHandle) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Focus left window: %s in display %" PRId32,
+ oldFocusedWindowHandle->getName().c_str(), displayId);
+ }
+ std::shared_ptr<InputChannel> focusedInputChannel =
+ getInputChannelLocked(oldFocusedWindowHandle->getToken());
+ if (focusedInputChannel) {
+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
+ "focus left window");
+ synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
+ enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/, reason);
+ }
+ mFocusedWindowHandlesByDisplay.erase(displayId);
+ }
+ if (newFocusedWindowHandle) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Focus entered window: %s in display %" PRId32,
+ newFocusedWindowHandle->getName().c_str(), displayId);
+ }
+ mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
+ enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/, reason);
+ }
+
+ if (mFocusedDisplayId == displayId) {
+ notifyFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
+ }
+}
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index b4d1079..8988714 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -115,7 +115,8 @@
const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>&
handlesPerDisplay) override;
virtual void setFocusedApplication(
- int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) override;
+ int32_t displayId,
+ const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) override;
virtual void setFocusedDisplay(int32_t displayId) override;
virtual void setInputDispatchMode(bool enabled, bool frozen) override;
virtual void setInputFilterEnabled(bool enabled) override;
@@ -177,7 +178,8 @@
void dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) REQUIRES(mLock);
// Enqueues a focus event.
- void enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) REQUIRES(mLock);
+ void enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus,
+ std::string_view reason) REQUIRES(mLock);
// Adds an event to a queue of recent events for debugging purposes.
void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock);
@@ -277,7 +279,7 @@
void postCommandLocked(std::unique_ptr<CommandEntry> commandEntry) REQUIRES(mLock);
nsecs_t processAnrsLocked() REQUIRES(mLock);
- nsecs_t getDispatchingTimeoutLocked(const sp<IBinder>& token) REQUIRES(mLock);
+ std::chrono::nanoseconds getDispatchingTimeoutLocked(const sp<IBinder>& token) REQUIRES(mLock);
// Input filter processing.
bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock);
@@ -306,6 +308,7 @@
std::shared_ptr<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const
REQUIRES(mLock);
bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
+ bool hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const REQUIRES(mLock);
/*
* Validate and update InputWindowHandles for a given display.
@@ -321,8 +324,8 @@
std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
// Focused applications.
- std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay
- GUARDED_BY(mLock);
+ std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>
+ mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock);
// Top focused display.
int32_t mFocusedDisplayId GUARDED_BY(mLock);
@@ -374,7 +377,7 @@
* The focused application at the time when no focused window was present.
* Used to raise an ANR when we have no focused window.
*/
- sp<InputApplicationHandle> mAwaitedFocusedApplication GUARDED_BY(mLock);
+ std::shared_ptr<InputApplicationHandle> mAwaitedFocusedApplication GUARDED_BY(mLock);
// Optimization: AnrTracker is used to quickly find which connection is due for a timeout next.
// AnrTracker must be kept in-sync with all responsive connection.waitQueues.
@@ -382,7 +385,7 @@
// Once a connection becomes unresponsive, its entries are removed from AnrTracker to
// prevent unneeded wakeups.
AnrTracker mAnrTracker GUARDED_BY(mLock);
- void extendAnrTimeoutsLocked(const sp<InputApplicationHandle>& application,
+ void extendAnrTimeoutsLocked(const std::shared_ptr<InputApplicationHandle>& application,
const sp<IBinder>& connectionToken,
std::chrono::nanoseconds timeoutExtension) REQUIRES(mLock);
@@ -426,8 +429,9 @@
bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle, int32_t x,
int32_t y) const REQUIRES(mLock);
bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
- std::string getApplicationWindowLabel(const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle);
+ std::string getApplicationWindowLabel(
+ const std::shared_ptr<InputApplicationHandle>& applicationHandle,
+ const sp<InputWindowHandle>& windowHandle);
// Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work
@@ -497,12 +501,15 @@
void onDispatchCycleBrokenLocked(nsecs_t currentTime, const sp<Connection>& connection)
REQUIRES(mLock);
void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
- const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
+ const sp<InputWindowHandle>& newFocus, int32_t displayId,
+ std::string_view reason) REQUIRES(mLock);
+ void notifyFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+ const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);
- void onAnrLocked(const sp<InputApplicationHandle>& application) REQUIRES(mLock);
+ void onAnrLocked(const std::shared_ptr<InputApplicationHandle>& application) REQUIRES(mLock);
void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason)
REQUIRES(mLock);
- void updateLastAnrStateLocked(const sp<InputApplicationHandle>& application,
+ void updateLastAnrStateLocked(const std::shared_ptr<InputApplicationHandle>& application,
const std::string& reason) REQUIRES(mLock);
void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason)
REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index f97c880..179a263 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -113,7 +113,8 @@
* This method may be called on any thread (usually by the input manager).
*/
virtual void setFocusedApplication(
- int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
+ int32_t displayId,
+ const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0;
/* Sets the focused display.
*
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index c886bee..d04d797 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -48,8 +48,8 @@
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual std::chrono::nanoseconds notifyAnr(
- const sp<InputApplicationHandle>& inputApplicationHandle, const sp<IBinder>& token,
- const std::string& reason) = 0;
+ const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
+ const sp<IBinder>& token, const std::string& reason) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index cef2b4c..8f34e8a 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -53,11 +53,10 @@
#define INDENT3 " "
using android::base::StringPrintf;
+using namespace android::flag_operators;
namespace android {
-static constexpr bool DEBUG = false;
-
static const char* DEVICE_PATH = "/dev/input";
// v4l2 devices go directly into /dev
static const char* VIDEO_DEVICE_PATH = "/dev";
@@ -127,9 +126,9 @@
// --- Global Functions ---
-uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
+Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
// Touch devices get dibs on touch-related axes.
- if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
+ if (deviceClasses.test(InputDeviceClass::TOUCH)) {
switch (axis) {
case ABS_X:
case ABS_Y:
@@ -151,27 +150,26 @@
case ABS_MT_TRACKING_ID:
case ABS_MT_PRESSURE:
case ABS_MT_DISTANCE:
- return INPUT_DEVICE_CLASS_TOUCH;
+ return InputDeviceClass::TOUCH;
}
}
// External stylus gets the pressure axis
- if (deviceClasses & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ if (deviceClasses.test(InputDeviceClass::EXTERNAL_STYLUS)) {
if (axis == ABS_PRESSURE) {
- return INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+ return InputDeviceClass::EXTERNAL_STYLUS;
}
}
// Joystick devices get the rest.
- return deviceClasses & INPUT_DEVICE_CLASS_JOYSTICK;
+ return deviceClasses & InputDeviceClass::JOYSTICK;
}
// --- EventHub::Device ---
EventHub::Device::Device(int fd, int32_t id, const std::string& path,
const InputDeviceIdentifier& identifier)
- : next(nullptr),
- fd(fd),
+ : fd(fd),
id(id),
path(path),
identifier(identifier),
@@ -212,10 +210,159 @@
return OK;
}
-bool EventHub::Device::hasValidFd() {
+bool EventHub::Device::hasValidFd() const {
return !isVirtual && enabled;
}
+const sp<KeyCharacterMap>& EventHub::Device::getKeyCharacterMap() const {
+ if (combinedKeyMap != nullptr) {
+ return combinedKeyMap;
+ }
+ return keyMap.keyCharacterMap;
+}
+
+template <std::size_t N>
+status_t EventHub::Device::readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) {
+ if (!hasValidFd()) {
+ return BAD_VALUE;
+ }
+ if ((_IOC_SIZE(ioctlCode) == 0)) {
+ ioctlCode |= _IOC(0, 0, 0, bitArray.bytes());
+ }
+
+ typename BitArray<N>::Buffer buffer;
+ status_t ret = ioctl(fd, ioctlCode, buffer.data());
+ bitArray.loadFromBuffer(buffer);
+ return ret;
+}
+
+void EventHub::Device::configureFd() {
+ // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
+ if (classes.test(InputDeviceClass::KEYBOARD)) {
+ // Disable kernel key repeat since we handle it ourselves
+ unsigned int repeatRate[] = {0, 0};
+ if (ioctl(fd, EVIOCSREP, repeatRate)) {
+ ALOGW("Unable to disable kernel key repeat for %s: %s", path.c_str(), strerror(errno));
+ }
+ }
+
+ // Tell the kernel that we want to use the monotonic clock for reporting timestamps
+ // associated with input events. This is important because the input system
+ // uses the timestamps extensively and assumes they were recorded using the monotonic
+ // clock.
+ int clockId = CLOCK_MONOTONIC;
+ bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
+ ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
+}
+
+bool EventHub::Device::hasKeycodeLocked(int keycode) const {
+ if (!keyMap.haveKeyLayout()) {
+ return false;
+ }
+
+ std::vector<int32_t> scanCodes;
+ keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
+ const size_t N = scanCodes.size();
+ for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
+ int32_t sc = scanCodes[i];
+ if (sc >= 0 && sc <= KEY_MAX && keyBitmask.test(sc)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void EventHub::Device::loadConfigurationLocked() {
+ configurationFile =
+ getInputDeviceConfigurationFilePathByDeviceIdentifier(identifier,
+ InputDeviceConfigurationFileType::
+ CONFIGURATION);
+ if (configurationFile.empty()) {
+ ALOGD("No input device configuration file found for device '%s'.", identifier.name.c_str());
+ } else {
+ status_t status = PropertyMap::load(String8(configurationFile.c_str()), &configuration);
+ if (status) {
+ ALOGE("Error loading input device configuration file for device '%s'. "
+ "Using default configuration.",
+ identifier.name.c_str());
+ }
+ }
+}
+
+bool EventHub::Device::loadVirtualKeyMapLocked() {
+ // The virtual key map is supplied by the kernel as a system board property file.
+ std::string propPath = "/sys/board_properties/virtualkeys.";
+ propPath += identifier.getCanonicalName();
+ if (access(propPath.c_str(), R_OK)) {
+ return false;
+ }
+ virtualKeyMap = VirtualKeyMap::load(propPath);
+ return virtualKeyMap != nullptr;
+}
+
+status_t EventHub::Device::loadKeyMapLocked() {
+ return keyMap.load(identifier, configuration);
+}
+
+bool EventHub::Device::isExternalDeviceLocked() {
+ if (configuration) {
+ bool value;
+ if (configuration->tryGetProperty(String8("device.internal"), value)) {
+ return !value;
+ }
+ }
+ return identifier.bus == BUS_USB || identifier.bus == BUS_BLUETOOTH;
+}
+
+bool EventHub::Device::deviceHasMicLocked() {
+ if (configuration) {
+ bool value;
+ if (configuration->tryGetProperty(String8("audio.mic"), value)) {
+ return value;
+ }
+ }
+ return false;
+}
+
+void EventHub::Device::setLedStateLocked(int32_t led, bool on) {
+ int32_t sc;
+ if (hasValidFd() && mapLed(led, &sc) != NAME_NOT_FOUND) {
+ struct input_event ev;
+ ev.time.tv_sec = 0;
+ ev.time.tv_usec = 0;
+ ev.type = EV_LED;
+ ev.code = sc;
+ ev.value = on ? 1 : 0;
+
+ ssize_t nWrite;
+ do {
+ nWrite = write(fd, &ev, sizeof(struct input_event));
+ } while (nWrite == -1 && errno == EINTR);
+ }
+}
+
+void EventHub::Device::setLedForControllerLocked() {
+ for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
+ setLedStateLocked(ALED_CONTROLLER_1 + i, controllerNumber == i + 1);
+ }
+}
+
+status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const {
+ if (!keyMap.haveKeyLayout()) {
+ return NAME_NOT_FOUND;
+ }
+
+ int32_t scanCode;
+ if (keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
+ if (scanCode >= 0 && scanCode <= LED_MAX && ledBitmask.test(scanCode)) {
+ *outScanCode = scanCode;
+ return NO_ERROR;
+ }
+ }
+ return NAME_NOT_FOUND;
+}
+
/**
* Get the capabilities for the current process.
* Crashes the system if unable to create / check / destroy the capabilities object.
@@ -265,8 +412,8 @@
: mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
mNextDeviceId(1),
mControllerNumbers(),
- mOpeningDevices(nullptr),
- mClosingDevices(nullptr),
+ mOpeningDevices(0),
+ mClosingDevices(0),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false),
mNeedToScanDevices(true),
@@ -321,11 +468,7 @@
EventHub::~EventHub(void) {
closeAllDevicesLocked();
- while (mClosingDevices) {
- Device* device = mClosingDevices;
- mClosingDevices = device->next;
- delete device;
- }
+ mClosingDevices.clear();
::close(mEpollFd);
::close(mINotifyFd);
@@ -336,28 +479,25 @@
InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device == nullptr) return InputDeviceIdentifier();
- return device->identifier;
+ return device != nullptr ? device->identifier : InputDeviceIdentifier();
}
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
+Flags<InputDeviceClass> EventHub::getDeviceClasses(int32_t deviceId) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device == nullptr) return 0;
- return device->classes;
+ return device != nullptr ? device->classes : Flags<InputDeviceClass>(0);
}
int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device == nullptr) return 0;
- return device->controllerNumber;
+ return device != nullptr ? device->controllerNumber : 0;
}
void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->configuration) {
+ if (device != nullptr && device->configuration) {
*outConfiguration = *device->configuration;
} else {
outConfiguration->clear();
@@ -397,7 +537,6 @@
bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
if (axis >= 0 && axis <= REL_MAX) {
AutoMutex _l(mLock);
-
Device* device = getDeviceLocked(deviceId);
return device != nullptr ? device->relBitmask.test(axis) : false;
}
@@ -405,13 +544,12 @@
}
bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
- if (property >= 0 && property <= INPUT_PROP_MAX) {
- AutoMutex _l(mLock);
+ AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- return device != nullptr ? device->propBitmask.test(property) : false;
- }
- return false;
+ Device* device = getDeviceLocked(deviceId);
+ return property >= 0 && property <= INPUT_PROP_MAX && device != nullptr
+ ? device->propBitmask.test(property)
+ : false;
}
int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
@@ -588,7 +726,7 @@
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
int32_t sc;
- if (device != nullptr && mapLed(device, led, &sc) == NO_ERROR) {
+ if (device != nullptr && device->mapLed(led, &sc) == NO_ERROR) {
return device->ledBitmask.test(sc);
}
return false;
@@ -597,23 +735,8 @@
void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- setLedStateLocked(device, led, on);
-}
-
-void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
- int32_t sc;
- if (device != nullptr && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_LED;
- ev.code = sc;
- ev.value = on ? 1 : 0;
-
- ssize_t nWrite;
- do {
- nWrite = write(device->fd, &ev, sizeof(struct input_event));
- } while (nWrite == -1 && errno == EINTR);
+ if (device != nullptr && device->hasValidFd()) {
+ device->setLedStateLocked(led, on);
}
}
@@ -760,11 +883,9 @@
}
EventHub::Device* EventHub::getDeviceByDescriptorLocked(const std::string& descriptor) const {
- size_t size = mDevices.size();
- for (size_t i = 0; i < size; i++) {
- Device* device = mDevices.valueAt(i);
+ for (const auto& [id, device] : mDevices) {
if (descriptor == device->identifier.descriptor) {
- return device;
+ return device.get();
}
}
return nullptr;
@@ -774,15 +895,14 @@
if (deviceId == ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID) {
deviceId = mBuiltInKeyboardId;
}
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : NULL;
+ const auto& it = mDevices.find(deviceId);
+ return it != mDevices.end() ? it->second.get() : nullptr;
}
EventHub::Device* EventHub::getDeviceByPathLocked(const std::string& devicePath) const {
- for (size_t i = 0; i < mDevices.size(); i++) {
- Device* device = mDevices.valueAt(i);
+ for (const auto& [id, device] : mDevices) {
if (device->path == devicePath) {
- return device;
+ return device.get();
}
}
return nullptr;
@@ -796,15 +916,14 @@
* devices are ignored.
*/
EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
- for (size_t i = 0; i < mDevices.size(); i++) {
- Device* device = mDevices.valueAt(i);
+ for (const auto& [id, device] : mDevices) {
if (device->fd == fd) {
// This is an input device event
- return device;
+ return device.get();
}
if (device->videoDevice && device->videoDevice->getFd() == fd) {
// This is a video device event
- return device;
+ return device.get();
}
}
// We do not check mUnattachedVideoDevices here because they should not participate in epoll,
@@ -837,17 +956,16 @@
}
// Report any devices that had last been added/removed.
- while (mClosingDevices) {
- Device* device = mClosingDevices;
+ for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
+ std::unique_ptr<Device> device = std::move(*it);
ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
- mClosingDevices = device->next;
event->when = now;
event->deviceId = (device->id == mBuiltInKeyboardId)
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
: device->id;
event->type = DEVICE_REMOVED;
event += 1;
- delete device;
+ it = mClosingDevices.erase(it);
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
@@ -860,14 +978,18 @@
mNeedToSendFinishedDeviceScan = true;
}
- while (mOpeningDevices != nullptr) {
- Device* device = mOpeningDevices;
+ for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end();) {
+ std::unique_ptr<Device> device = std::move(*it);
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
- mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED;
event += 1;
+ auto [dev_it, insert] = mDevices.insert_or_assign(device->id, std::move(device));
+ if (!insert) {
+ ALOGW("Device id %d exists, replaced.", device->id);
+ }
+ it = mOpeningDevices.erase(it);
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
@@ -914,7 +1036,7 @@
}
Device* device = getDeviceByFdLocked(eventItem.data.fd);
- if (!device) {
+ if (device == nullptr) {
ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
eventItem.data.fd);
ALOG_ASSERT(!DEBUG);
@@ -950,7 +1072,7 @@
" bufferSize: %zu capacity: %zu errno: %d)\n",
device->fd, readSize, bufferSize, capacity, errno);
deviceChanged = true;
- closeDeviceLocked(device);
+ closeDeviceLocked(*device);
} else if (readSize < 0) {
if (errno != EAGAIN && errno != EINTR) {
ALOGW("could not get event (errno=%d)", errno);
@@ -982,7 +1104,7 @@
ALOGI("Removing device %s due to epoll hang-up event.",
device->identifier.name.c_str());
deviceChanged = true;
- closeDeviceLocked(device);
+ closeDeviceLocked(*device);
} else {
ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
device->identifier.name.c_str());
@@ -1087,7 +1209,7 @@
ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
}
}
- if (mDevices.indexOfKey(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) < 0) {
+ if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
createVirtualKeyboardLocked();
}
}
@@ -1123,20 +1245,14 @@
return OK;
}
-status_t EventHub::registerDeviceForEpollLocked(Device* device) {
- if (device == nullptr) {
- if (DEBUG) {
- LOG_ALWAYS_FATAL("Cannot call registerDeviceForEpollLocked with null Device");
- }
- return BAD_VALUE;
- }
- status_t result = registerFdForEpoll(device->fd);
+status_t EventHub::registerDeviceForEpollLocked(Device& device) {
+ status_t result = registerFdForEpoll(device.fd);
if (result != OK) {
- ALOGE("Could not add input device fd to epoll for device %" PRId32, device->id);
+ ALOGE("Could not add input device fd to epoll for device %" PRId32, device.id);
return result;
}
- if (device->videoDevice) {
- registerVideoDeviceForEpollLocked(*device->videoDevice);
+ if (device.videoDevice) {
+ registerVideoDeviceForEpollLocked(*device.videoDevice);
}
return result;
}
@@ -1148,16 +1264,16 @@
}
}
-status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
- if (device->hasValidFd()) {
- status_t result = unregisterFdFromEpoll(device->fd);
+status_t EventHub::unregisterDeviceFromEpollLocked(Device& device) {
+ if (device.hasValidFd()) {
+ status_t result = unregisterFdFromEpoll(device.fd);
if (result != OK) {
- ALOGW("Could not remove input device fd from epoll for device %" PRId32, device->id);
+ ALOGW("Could not remove input device fd from epoll for device %" PRId32, device.id);
return result;
}
}
- if (device->videoDevice) {
- unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+ if (device.videoDevice) {
+ unregisterVideoDeviceFromEpollLocked(*device.videoDevice);
}
return OK;
}
@@ -1244,7 +1360,7 @@
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
- Device* device = new Device(fd, deviceId, devicePath, identifier);
+ std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
@@ -1260,7 +1376,7 @@
driverVersion & 0xff);
// Load the configuration file for the device.
- loadConfigurationLocked(device);
+ device->loadConfigurationLocked();
// Figure out the kinds of events the device reports.
device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
@@ -1278,13 +1394,13 @@
bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) ||
device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI);
if (haveKeyboardKeys || haveGamepadButtons) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+ device->classes |= InputDeviceClass::KEYBOARD;
}
// See if this is a cursor device such as a trackball or mouse.
if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) &&
device->relBitmask.test(REL_Y)) {
- device->classes |= INPUT_DEVICE_CLASS_CURSOR;
+ device->classes |= InputDeviceClass::CURSOR;
}
// See if this is a rotary encoder type device.
@@ -1292,7 +1408,7 @@
if (device->configuration &&
device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
if (!deviceType.compare(String8("rotaryEncoder"))) {
- device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
+ device->classes |= InputDeviceClass::ROTARY_ENCODER;
}
}
@@ -1303,30 +1419,30 @@
// with the ABS_MT range. Try to confirm that the device really is
// a touch screen.
if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
+ device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);
}
// Is this an old style single-touch driver?
} else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&
device->absBitmask.test(ABS_Y)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCH;
+ device->classes |= InputDeviceClass::TOUCH;
// Is this a BT stylus?
} else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) &&
!device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) {
- device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+ device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
// Keyboard will try to claim some of the buttons but we really want to reserve those so we
// can fuse it with the touch screen data, so just take them back. Note this means an
// external stylus cannot also be a keyboard device.
- device->classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
+ device->classes &= ~InputDeviceClass::KEYBOARD;
}
// See if this device is a joystick.
// Assumes that joysticks always have gamepad buttons in order to distinguish them
// from other devices such as accelerometers that also have absolute axes.
if (haveGamepadButtons) {
- uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
+ auto assumedClasses = device->classes | InputDeviceClass::JOYSTICK;
for (int i = 0; i <= ABS_MAX; i++) {
if (device->absBitmask.test(i) &&
- (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
+ (getAbsAxisUsage(i, assumedClasses).test(InputDeviceClass::JOYSTICK))) {
device->classes = assumedClasses;
break;
}
@@ -1336,36 +1452,36 @@
// Check whether this device has switches.
for (int i = 0; i <= SW_MAX; i++) {
if (device->swBitmask.test(i)) {
- device->classes |= INPUT_DEVICE_CLASS_SWITCH;
+ device->classes |= InputDeviceClass::SWITCH;
break;
}
}
// Check whether this device supports the vibrator.
if (device->ffBitmask.test(FF_RUMBLE)) {
- device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;
+ device->classes |= InputDeviceClass::VIBRATOR;
}
// Configure virtual keys.
- if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
+ if ((device->classes.test(InputDeviceClass::TOUCH))) {
// Load the virtual keys for the touch screen, if any.
// We do this now so that we can make sure to load the keymap if necessary.
- bool success = loadVirtualKeyMapLocked(device);
+ bool success = device->loadVirtualKeyMapLocked();
if (success) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+ device->classes |= InputDeviceClass::KEYBOARD;
}
}
// Load the key map.
// We need to do this for joysticks too because the key layout may specify axes.
status_t keyMapStatus = NAME_NOT_FOUND;
- if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
+ if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK)) {
// Load the keymap for the device.
- keyMapStatus = loadKeyMapLocked(device);
+ keyMapStatus = device->loadKeyMapLocked();
}
// Configure the keyboard, gamepad or virtual keyboard.
- if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+ if (device->classes.test(InputDeviceClass::KEYBOARD)) {
// Register the keyboard as a built-in keyboard if it is eligible.
if (!keyMapStatus && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD &&
isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) {
@@ -1373,50 +1489,49 @@
}
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (hasKeycodeLocked(device, AKEYCODE_Q)) {
- device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
+ if (device->hasKeycodeLocked(AKEYCODE_Q)) {
+ device->classes |= InputDeviceClass::ALPHAKEY;
}
// See if this device has a DPAD.
- if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
- device->classes |= INPUT_DEVICE_CLASS_DPAD;
+ if (device->hasKeycodeLocked(AKEYCODE_DPAD_UP) &&
+ device->hasKeycodeLocked(AKEYCODE_DPAD_DOWN) &&
+ device->hasKeycodeLocked(AKEYCODE_DPAD_LEFT) &&
+ device->hasKeycodeLocked(AKEYCODE_DPAD_RIGHT) &&
+ device->hasKeycodeLocked(AKEYCODE_DPAD_CENTER)) {
+ device->classes |= InputDeviceClass::DPAD;
}
// See if this device has a gamepad.
for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {
- if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
- device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
+ if (device->hasKeycodeLocked(GAMEPAD_KEYCODES[i])) {
+ device->classes |= InputDeviceClass::GAMEPAD;
break;
}
}
}
// If the device isn't recognized as something we handle, don't monitor it.
- if (device->classes == 0) {
+ if (device->classes == Flags<InputDeviceClass>(0)) {
ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
device->identifier.name.c_str());
- delete device;
return -1;
}
// Determine whether the device has a mic.
- if (deviceHasMicLocked(device)) {
- device->classes |= INPUT_DEVICE_CLASS_MIC;
+ if (device->deviceHasMicLocked()) {
+ device->classes |= InputDeviceClass::MIC;
}
// Determine whether the device is external or internal.
- if (isExternalDeviceLocked(device)) {
- device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
+ if (device->isExternalDeviceLocked()) {
+ device->classes |= InputDeviceClass::EXTERNAL;
}
- if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD) &&
- device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
- device->controllerNumber = getNextControllerNumberLocked(device);
- setLedForControllerLocked(device);
+ if (device->classes.any(InputDeviceClass::JOYSTICK | InputDeviceClass::DPAD) &&
+ device->classes.test(InputDeviceClass::GAMEPAD)) {
+ device->controllerNumber = getNextControllerNumberLocked(device->identifier.name);
+ device->setLedForControllerLocked();
}
// Find a matching video device by comparing device names
@@ -1434,43 +1549,23 @@
}),
mUnattachedVideoDevices.end());
- if (registerDeviceForEpollLocked(device) != OK) {
- delete device;
+ if (registerDeviceForEpollLocked(*device) != OK) {
return -1;
}
- configureFd(device);
+ device->configureFd();
- ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
+ ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
- deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(), device->classes,
- device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
- device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
+ deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),
+ device->classes.string().c_str(), device->configurationFile.c_str(),
+ device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),
+ toString(mBuiltInKeyboardId == deviceId));
- addDeviceLocked(device);
+ addDeviceLocked(std::move(device));
return OK;
}
-void EventHub::configureFd(Device* device) {
- // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
- if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
- // Disable kernel key repeat since we handle it ourselves
- unsigned int repeatRate[] = {0, 0};
- if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
- ALOGW("Unable to disable kernel key repeat for %s: %s", device->path.c_str(),
- strerror(errno));
- }
- }
-
- // Tell the kernel that we want to use the monotonic clock for reporting timestamps
- // associated with input events. This is important because the input system
- // uses the timestamps extensively and assumes they were recorded using the monotonic
- // clock.
- int clockId = CLOCK_MONOTONIC;
- bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
- ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
-}
-
void EventHub::openVideoDeviceLocked(const std::string& devicePath) {
std::unique_ptr<TouchVideoDevice> videoDevice = TouchVideoDevice::create(devicePath);
if (!videoDevice) {
@@ -1478,8 +1573,7 @@
return;
}
// Transfer ownership of this video device to a matching input device
- for (size_t i = 0; i < mDevices.size(); i++) {
- Device* device = mDevices.valueAt(i);
+ for (const auto& [id, device] : mDevices) {
if (videoDevice->getName() == device->identifier.name) {
device->videoDevice = std::move(videoDevice);
if (device->enabled) {
@@ -1523,9 +1617,9 @@
return result;
}
- configureFd(device);
+ device->configureFd();
- return registerDeviceForEpollLocked(device);
+ return registerDeviceForEpollLocked(*device);
}
status_t EventHub::disableDevice(int32_t deviceId) {
@@ -1539,7 +1633,7 @@
ALOGW("Duplicate call to %s, input device already disabled", __func__);
return OK;
}
- unregisterDeviceFromEpollLocked(device);
+ unregisterDeviceFromEpollLocked(*device);
return device->disable();
}
@@ -1549,79 +1643,23 @@
identifier.uniqueId = "<virtual>";
assignDescriptorLocked(identifier);
- Device* device =
- new Device(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>", identifier);
- device->classes = INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY |
- INPUT_DEVICE_CLASS_DPAD | INPUT_DEVICE_CLASS_VIRTUAL;
- loadKeyMapLocked(device);
- addDeviceLocked(device);
+ std::unique_ptr<Device> device =
+ std::make_unique<Device>(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
+ identifier);
+ device->classes = InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY |
+ InputDeviceClass::DPAD | InputDeviceClass::VIRTUAL;
+ device->loadKeyMapLocked();
+ addDeviceLocked(std::move(device));
}
-void EventHub::addDeviceLocked(Device* device) {
- mDevices.add(device->id, device);
- device->next = mOpeningDevices;
- mOpeningDevices = device;
+void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
+ mOpeningDevices.push_back(std::move(device));
}
-void EventHub::loadConfigurationLocked(Device* device) {
- device->configurationFile =
- getInputDeviceConfigurationFilePathByDeviceIdentifier(device->identifier,
- InputDeviceConfigurationFileType::
- CONFIGURATION);
- if (device->configurationFile.empty()) {
- ALOGD("No input device configuration file found for device '%s'.",
- device->identifier.name.c_str());
- } else {
- status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
- &device->configuration);
- if (status) {
- ALOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- device->identifier.name.c_str());
- }
- }
-}
-
-bool EventHub::loadVirtualKeyMapLocked(Device* device) {
- // The virtual key map is supplied by the kernel as a system board property file.
- std::string path;
- path += "/sys/board_properties/virtualkeys.";
- path += device->identifier.getCanonicalName();
- if (access(path.c_str(), R_OK)) {
- return false;
- }
- device->virtualKeyMap = VirtualKeyMap::load(path);
- return device->virtualKeyMap != nullptr;
-}
-
-status_t EventHub::loadKeyMapLocked(Device* device) {
- return device->keyMap.load(device->identifier, device->configuration);
-}
-
-bool EventHub::isExternalDeviceLocked(Device* device) {
- if (device->configuration) {
- bool value;
- if (device->configuration->tryGetProperty(String8("device.internal"), value)) {
- return !value;
- }
- }
- return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
-}
-
-bool EventHub::deviceHasMicLocked(Device* device) {
- if (device->configuration) {
- bool value;
- if (device->configuration->tryGetProperty(String8("audio.mic"), value)) {
- return value;
- }
- }
- return false;
-}
-
-int32_t EventHub::getNextControllerNumberLocked(Device* device) {
+int32_t EventHub::getNextControllerNumberLocked(const std::string& name) {
if (mControllerNumbers.isFull()) {
ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
- device->identifier.name.c_str());
+ name.c_str());
return 0;
}
// Since the controller number 0 is reserved for non-controllers, translate all numbers up by
@@ -1629,58 +1667,16 @@
return static_cast<int32_t>(mControllerNumbers.markFirstUnmarkedBit() + 1);
}
-void EventHub::releaseControllerNumberLocked(Device* device) {
- int32_t num = device->controllerNumber;
- device->controllerNumber = 0;
- if (num == 0) {
- return;
+void EventHub::releaseControllerNumberLocked(int32_t num) {
+ if (num > 0) {
+ mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
}
- mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
-}
-
-void EventHub::setLedForControllerLocked(Device* device) {
- for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
- setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
- }
-}
-
-bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
- if (!device->keyMap.haveKeyLayout()) {
- return false;
- }
-
- std::vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
- const size_t N = scanCodes.size();
- for (size_t i = 0; i < N && i <= KEY_MAX; i++) {
- int32_t sc = scanCodes[i];
- if (sc >= 0 && sc <= KEY_MAX && device->keyBitmask.test(sc)) {
- return true;
- }
- }
-
- return false;
-}
-
-status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) const {
- if (!device->keyMap.haveKeyLayout()) {
- return NAME_NOT_FOUND;
- }
-
- int32_t scanCode;
- if (device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
- if (scanCode >= 0 && scanCode <= LED_MAX && device->ledBitmask.test(scanCode)) {
- *outScanCode = scanCode;
- return NO_ERROR;
- }
- }
- return NAME_NOT_FOUND;
}
void EventHub::closeDeviceByPathLocked(const std::string& devicePath) {
Device* device = getDeviceByPathLocked(devicePath);
- if (device) {
- closeDeviceLocked(device);
+ if (device != nullptr) {
+ closeDeviceLocked(*device);
return;
}
ALOGV("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
@@ -1694,8 +1690,7 @@
void EventHub::closeVideoDeviceByPathLocked(const std::string& devicePath) {
// A video device may be owned by an existing input device, or it may be stored in
// the mUnattachedVideoDevices queue. Check both locations.
- for (size_t i = 0; i < mDevices.size(); i++) {
- Device* device = mDevices.valueAt(i);
+ for (const auto& [id, device] : mDevices) {
if (device->videoDevice && device->videoDevice->getPath() == devicePath) {
unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
device->videoDevice = nullptr;
@@ -1713,60 +1708,34 @@
void EventHub::closeAllDevicesLocked() {
mUnattachedVideoDevices.clear();
- while (mDevices.size() > 0) {
- closeDeviceLocked(mDevices.valueAt(mDevices.size() - 1));
+ for (const auto& [id, device] : mDevices) {
+ closeDeviceLocked(*device);
}
}
-void EventHub::closeDeviceLocked(Device* device) {
- ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x", device->path.c_str(),
- device->identifier.name.c_str(), device->id, device->fd, device->classes);
+void EventHub::closeDeviceLocked(Device& device) {
+ ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=%s", device.path.c_str(),
+ device.identifier.name.c_str(), device.id, device.fd, device.classes.string().c_str());
- if (device->id == mBuiltInKeyboardId) {
+ if (device.id == mBuiltInKeyboardId) {
ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
- device->path.c_str(), mBuiltInKeyboardId);
+ device.path.c_str(), mBuiltInKeyboardId);
mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
}
unregisterDeviceFromEpollLocked(device);
- if (device->videoDevice) {
+ if (device.videoDevice) {
// This must be done after the video device is removed from epoll
- mUnattachedVideoDevices.push_back(std::move(device->videoDevice));
+ mUnattachedVideoDevices.push_back(std::move(device.videoDevice));
}
- releaseControllerNumberLocked(device);
+ releaseControllerNumberLocked(device.controllerNumber);
+ device.close();
- mDevices.removeItem(device->id);
- device->close();
-
- // Unlink for opening devices list if it is present.
- Device* pred = nullptr;
- bool found = false;
- for (Device* entry = mOpeningDevices; entry != nullptr;) {
- if (entry == device) {
- found = true;
- break;
- }
- pred = entry;
- entry = entry->next;
- }
- if (found) {
- // Unlink the device from the opening devices list then delete it.
- // We don't need to tell the client that the device was closed because
- // it does not even know it was opened in the first place.
- ALOGI("Device %s was immediately closed after opening.", device->path.c_str());
- if (pred) {
- pred->next = device->next;
- } else {
- mOpeningDevices = device->next;
- }
- delete device;
- } else {
- // Link into closing devices list.
- // The device will be deleted later after we have informed the client.
- device->next = mClosingDevices;
- mClosingDevices = device;
- }
+ // Move device to mClosingDevices
+ mClosingDevices.push_back(std::move(mDevices[device.id]));
+ // Erase device from mDevices
+ mDevices.erase(device.id);
}
status_t EventHub::readNotifyLocked() {
@@ -1853,8 +1822,7 @@
dump += INDENT "Devices:\n";
- for (size_t i = 0; i < mDevices.size(); i++) {
- const Device* device = mDevices.valueAt(i);
+ for (const auto& [id, device] : mDevices) {
if (mBuiltInKeyboardId == device->id) {
dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
device->id, device->identifier.name.c_str());
@@ -1862,7 +1830,7 @@
dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
device->identifier.name.c_str());
}
- dump += StringPrintf(INDENT3 "Classes: 0x%08x\n", device->classes);
+ dump += StringPrintf(INDENT3 "Classes: %s\n", device->classes.string().c_str());
dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(device->enabled));
dump += StringPrintf(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.c_str());
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index b4eaf7f..14f922f 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -18,6 +18,7 @@
#include "InputDevice.h"
+#include <input/Flags.h>
#include <algorithm>
#include "CursorInputMapper.h"
@@ -131,7 +132,7 @@
return;
}
std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
- uint32_t classes = contextPtr->getDeviceClasses();
+ Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();
std::vector<std::unique_ptr<InputMapper>> mappers;
// Check if we should skip population
@@ -141,33 +142,33 @@
}
// Switch-like devices.
- if (classes & INPUT_DEVICE_CLASS_SWITCH) {
+ if (classes.test(InputDeviceClass::SWITCH)) {
mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
}
// Scroll wheel-like devices.
- if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
+ if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
}
// Vibrator-like devices.
- if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
+ if (classes.test(InputDeviceClass::VIBRATOR)) {
mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
}
// Keyboard-like devices.
uint32_t keyboardSource = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
- if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+ if (classes.test(InputDeviceClass::KEYBOARD)) {
keyboardSource |= AINPUT_SOURCE_KEYBOARD;
}
- if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
+ if (classes.test(InputDeviceClass::ALPHAKEY)) {
keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
}
- if (classes & INPUT_DEVICE_CLASS_DPAD) {
+ if (classes.test(InputDeviceClass::DPAD)) {
keyboardSource |= AINPUT_SOURCE_DPAD;
}
- if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
+ if (classes.test(InputDeviceClass::GAMEPAD)) {
keyboardSource |= AINPUT_SOURCE_GAMEPAD;
}
@@ -177,24 +178,24 @@
}
// Cursor-like devices.
- if (classes & INPUT_DEVICE_CLASS_CURSOR) {
+ if (classes.test(InputDeviceClass::CURSOR)) {
mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
}
// Touchscreens and touchpad devices.
- if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
+ if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
- } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
+ } else if (classes.test(InputDeviceClass::TOUCH)) {
mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
}
// Joystick-like devices.
- if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
+ if (classes.test(InputDeviceClass::JOYSTICK)) {
mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
}
// External stylus-like devices.
- if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
}
@@ -209,7 +210,7 @@
void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
uint32_t changes) {
mSources = 0;
- mClasses = 0;
+ mClasses = Flags<InputDeviceClass>(0);
mControllerNumber = 0;
for_each_subdevice([this](InputDeviceContext& context) {
@@ -224,8 +225,8 @@
}
});
- mIsExternal = !!(mClasses & INPUT_DEVICE_CLASS_EXTERNAL);
- mHasMic = !!(mClasses & INPUT_DEVICE_CLASS_MIC);
+ mIsExternal = mClasses.test(InputDeviceClass::EXTERNAL);
+ mHasMic = mClasses.test(InputDeviceClass::MIC);
if (!isIgnored()) {
if (!changes) { // first time only
@@ -238,7 +239,7 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
+ if (!mClasses.test(InputDeviceClass::VIRTUAL)) {
sp<KeyCharacterMap> keyboardLayout =
mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
bool shouldBumpGeneration = false;
@@ -255,7 +256,7 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
+ if (!(mClasses.test(InputDeviceClass::VIRTUAL))) {
std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
if (mAlias != alias) {
mAlias = alias;
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 16fe865..bb1ccbf 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -208,7 +208,7 @@
mDevices.emplace(eventHubId, device);
bumpGenerationLocked();
- if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {
notifyExternalStylusPresenceChanged();
}
}
@@ -237,7 +237,7 @@
device->removeEventHubDevice(eventHubId);
- if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {
notifyExternalStylusPresenceChanged();
}
@@ -360,7 +360,7 @@
void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
for (auto& devicePair : mDevices) {
std::shared_ptr<InputDevice>& device = devicePair.second;
- if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
+ if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS) && !device->isIgnored()) {
InputDeviceInfo info;
device->getDeviceInfo(&info);
outDevices.push_back(info);
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index c5dfcfd..80e80cb 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -19,8 +19,10 @@
#include <bitset>
#include <climits>
+#include <unordered_map>
#include <vector>
+#include <input/Flags.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/KeyCharacterMap.h>
@@ -76,58 +78,58 @@
/*
* Input device classes.
*/
-enum {
+enum class InputDeviceClass : uint32_t {
/* The input device is a keyboard or has buttons. */
- INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
+ KEYBOARD = 0x00000001,
/* The input device is an alpha-numeric keyboard (not just a dial pad). */
- INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
+ ALPHAKEY = 0x00000002,
/* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
- INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
+ TOUCH = 0x00000004,
/* The input device is a cursor device such as a trackball or mouse. */
- INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
+ CURSOR = 0x00000008,
/* The input device is a multi-touch touchscreen. */
- INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
+ TOUCH_MT = 0x00000010,
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
- INPUT_DEVICE_CLASS_DPAD = 0x00000020,
+ DPAD = 0x00000020,
/* The input device is a gamepad (implies keyboard, has BUTTON keys). */
- INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
+ GAMEPAD = 0x00000040,
/* The input device has switches. */
- INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
+ SWITCH = 0x00000080,
/* The input device is a joystick (implies gamepad, has joystick absolute axes). */
- INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
+ JOYSTICK = 0x00000100,
/* The input device has a vibrator (supports FF_RUMBLE). */
- INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
+ VIBRATOR = 0x00000200,
/* The input device has a microphone. */
- INPUT_DEVICE_CLASS_MIC = 0x00000400,
+ MIC = 0x00000400,
/* The input device is an external stylus (has data we want to fuse with touch data). */
- INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
+ EXTERNAL_STYLUS = 0x00000800,
/* The input device has a rotary encoder */
- INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
+ ROTARY_ENCODER = 0x00001000,
/* The input device is virtual (not a real device, not part of UI configuration). */
- INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
+ VIRTUAL = 0x40000000,
/* The input device is external (not built-in). */
- INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
+ EXTERNAL = 0x80000000,
};
/*
* Gets the class that owns an axis, in cases where multiple classes might claim
* the same axis for different purposes.
*/
-extern uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses);
+extern Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses);
/*
* Grand Central Station for events.
@@ -160,7 +162,7 @@
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
};
- virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
+ virtual Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const = 0;
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
@@ -327,69 +329,74 @@
public:
EventHub();
- virtual uint32_t getDeviceClasses(int32_t deviceId) const override;
+ Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override final;
- virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override;
+ InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override final;
- virtual int32_t getDeviceControllerNumber(int32_t deviceId) const override;
+ int32_t getDeviceControllerNumber(int32_t deviceId) const override final;
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override;
+ void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override final;
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const override;
+ status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+ RawAbsoluteAxisInfo* outAxisInfo) const override final;
- virtual bool hasRelativeAxis(int32_t deviceId, int axis) const override;
+ bool hasRelativeAxis(int32_t deviceId, int axis) const override final;
- virtual bool hasInputProperty(int32_t deviceId, int property) const override;
+ bool hasInputProperty(int32_t deviceId, int property) const override final;
- virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t metaState, int32_t* outKeycode, int32_t* outMetaState,
- uint32_t* outFlags) const override;
+ status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
+ int32_t* outKeycode, int32_t* outMetaState,
+ uint32_t* outFlags) const override final;
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
- AxisInfo* outAxisInfo) const override;
+ status_t mapAxis(int32_t deviceId, int32_t scanCode,
+ AxisInfo* outAxisInfo) const override final;
- virtual void setExcludedDevices(const std::vector<std::string>& devices) override;
+ void setExcludedDevices(const std::vector<std::string>& devices) override final;
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override;
- virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override;
- virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const override;
- virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const override;
+ int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final;
+ int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override final;
+ int32_t getSwitchState(int32_t deviceId, int32_t sw) const override final;
+ status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+ int32_t* outValue) const override final;
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const override;
+ bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) const override final;
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override;
- virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override;
+ size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override final;
+ std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override final;
- virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const override;
- virtual bool hasLed(int32_t deviceId, int32_t led) const override;
- virtual void setLedState(int32_t deviceId, int32_t led, bool on) override;
+ bool hasScanCode(int32_t deviceId, int32_t scanCode) const override final;
+ bool hasLed(int32_t deviceId, int32_t led) const override final;
+ void setLedState(int32_t deviceId, int32_t led, bool on) override final;
- virtual void getVirtualKeyDefinitions(
- int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override;
+ void getVirtualKeyDefinitions(
+ int32_t deviceId,
+ std::vector<VirtualKeyDefinition>& outVirtualKeys) const override final;
- virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override;
- virtual bool setKeyboardLayoutOverlay(int32_t deviceId,
- const sp<KeyCharacterMap>& map) override;
+ sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override final;
+ bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) override final;
- virtual void vibrate(int32_t deviceId, const VibrationElement& effect) override;
- virtual void cancelVibrate(int32_t deviceId) override;
+ void vibrate(int32_t deviceId, const VibrationElement& effect) override final;
+ void cancelVibrate(int32_t deviceId) override final;
- virtual void requestReopenDevices() override;
+ void requestReopenDevices() override final;
- virtual void wake() override;
+ void wake() override final;
- virtual void dump(std::string& dump) override;
- virtual void monitor() override;
+ void dump(std::string& dump) override final;
- virtual ~EventHub() override;
+ void monitor() override final;
+
+ bool isDeviceEnabled(int32_t deviceId) override final;
+
+ status_t enableDevice(int32_t deviceId) override final;
+
+ status_t disableDevice(int32_t deviceId) override final;
+
+ ~EventHub() override;
private:
struct Device {
- Device* next;
-
int fd; // may be -1 if device is closed
const int32_t id;
const std::string path;
@@ -397,7 +404,7 @@
std::unique_ptr<TouchVideoDevice> videoDevice;
- uint32_t classes;
+ Flags<InputDeviceClass> classes;
BitArray<KEY_MAX> keyBitmask;
BitArray<KEY_MAX> keyState;
@@ -431,53 +438,42 @@
bool enabled; // initially true
status_t enable();
status_t disable();
- bool hasValidFd();
+ bool hasValidFd() const;
const bool isVirtual; // set if fd < 0 is passed to constructor
- const sp<KeyCharacterMap>& getKeyCharacterMap() const {
- if (combinedKeyMap != nullptr) {
- return combinedKeyMap;
- }
- return keyMap.keyCharacterMap;
- }
+ const sp<KeyCharacterMap>& getKeyCharacterMap() const;
template <std::size_t N>
- status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) {
- if (!hasValidFd()) {
- return BAD_VALUE;
- }
- if ((_IOC_SIZE(ioctlCode) == 0)) {
- ioctlCode |= _IOC(0, 0, 0, bitArray.bytes());
- }
+ status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray);
- typename BitArray<N>::Buffer buffer;
- status_t ret = ioctl(fd, ioctlCode, buffer.data());
- bitArray.loadFromBuffer(buffer);
- return ret;
- }
+ void configureFd();
+ bool hasKeycodeLocked(int keycode) const;
+ void loadConfigurationLocked();
+ bool loadVirtualKeyMapLocked();
+ status_t loadKeyMapLocked();
+ bool isExternalDeviceLocked();
+ bool deviceHasMicLocked();
+ void setLedForControllerLocked();
+ status_t mapLed(int32_t led, int32_t* outScanCode) const;
+ void setLedStateLocked(int32_t led, bool on);
};
status_t openDeviceLocked(const std::string& devicePath);
void openVideoDeviceLocked(const std::string& devicePath);
void createVirtualKeyboardLocked();
- void addDeviceLocked(Device* device);
+ void addDeviceLocked(std::unique_ptr<Device> device);
void assignDescriptorLocked(InputDeviceIdentifier& identifier);
void closeDeviceByPathLocked(const std::string& devicePath);
void closeVideoDeviceByPathLocked(const std::string& devicePath);
- void closeDeviceLocked(Device* device);
+ void closeDeviceLocked(Device& device);
void closeAllDevicesLocked();
- void configureFd(Device* device);
-
- bool isDeviceEnabled(int32_t deviceId) override;
- status_t enableDevice(int32_t deviceId) override;
- status_t disableDevice(int32_t deviceId) override;
status_t registerFdForEpoll(int fd);
status_t unregisterFdFromEpoll(int fd);
- status_t registerDeviceForEpollLocked(Device* device);
+ status_t registerDeviceForEpollLocked(Device& device);
void registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice);
- status_t unregisterDeviceFromEpollLocked(Device* device);
+ status_t unregisterDeviceFromEpollLocked(Device& device);
void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
status_t scanDirLocked(const std::string& dirname);
@@ -494,21 +490,8 @@
*/
Device* getDeviceByFdLocked(int fd) const;
- bool hasKeycodeLocked(Device* device, int keycode) const;
-
- void loadConfigurationLocked(Device* device);
- bool loadVirtualKeyMapLocked(Device* device);
- status_t loadKeyMapLocked(Device* device);
-
- bool isExternalDeviceLocked(Device* device);
- bool deviceHasMicLocked(Device* device);
-
- int32_t getNextControllerNumberLocked(Device* device);
- void releaseControllerNumberLocked(Device* device);
- void setLedForControllerLocked(Device* device);
-
- status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
- void setLedStateLocked(Device* device, int32_t led, bool on);
+ int32_t getNextControllerNumberLocked(const std::string& name);
+ void releaseControllerNumberLocked(int32_t num);
// Protect all internal state.
mutable Mutex mLock;
@@ -526,7 +509,7 @@
BitSet32 mControllerNumbers;
- KeyedVector<int32_t, Device*> mDevices;
+ std::unordered_map<int32_t, std::unique_ptr<Device>> mDevices;
/**
* Video devices that report touchscreen heatmap, but have not (yet) been paired
* with a specific input device. Video device discovery is independent from input device
@@ -536,8 +519,8 @@
*/
std::vector<std::unique_ptr<TouchVideoDevice>> mUnattachedVideoDevices;
- Device* mOpeningDevices;
- Device* mClosingDevices;
+ std::vector<std::unique_ptr<Device>> mOpeningDevices;
+ std::vector<std::unique_ptr<Device>> mClosingDevices;
bool mNeedToSendFinishedDeviceScan;
bool mNeedToReopenDevices;
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 6cb86bd..da36a48 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -18,6 +18,7 @@
#define _UI_INPUTREADER_INPUT_DEVICE_H
#include <input/DisplayViewport.h>
+#include <input/Flags.h>
#include <input/InputDevice.h>
#include <stdint.h>
#include <utils/PropertyMap.h>
@@ -48,7 +49,7 @@
inline int32_t getGeneration() const { return mGeneration; }
inline const std::string getName() const { return mIdentifier.name; }
inline const std::string getDescriptor() { return mIdentifier.descriptor; }
- inline uint32_t getClasses() const { return mClasses; }
+ inline Flags<InputDeviceClass> getClasses() const { return mClasses; }
inline uint32_t getSources() const { return mSources; }
inline bool hasEventHubDevices() const { return !mDevices.empty(); }
@@ -121,7 +122,7 @@
int32_t mControllerNumber;
InputDeviceIdentifier mIdentifier;
std::string mAlias;
- uint32_t mClasses;
+ Flags<InputDeviceClass> mClasses;
// map from eventHubId to device context and mappers
using MapperVector = std::vector<std::unique_ptr<InputMapper>>;
@@ -206,7 +207,9 @@
inline int32_t getId() { return mDeviceId; }
inline int32_t getEventHubId() { return mId; }
- inline uint32_t getDeviceClasses() const { return mEventHub->getDeviceClasses(mId); }
+ inline Flags<InputDeviceClass> getDeviceClasses() const {
+ return mEventHub->getDeviceClasses(mId);
+ }
inline InputDeviceIdentifier getDeviceIdentifier() const {
return mEventHub->getDeviceIdentifier(mId);
}
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index d1f20c7..254b64b 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -82,6 +82,10 @@
} else {
info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -1.0f, 1.0f, 0.0f, mXScale,
+ 0.0f);
+ info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale,
+ 0.0f);
}
info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
@@ -314,7 +318,7 @@
mPointerVelocityControl.move(when, &deltaX, &deltaY);
- int32_t displayId;
+ int32_t displayId = ADISPLAY_ID_NONE;
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
if (mSource == AINPUT_SOURCE_MOUSE) {
@@ -338,10 +342,12 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
displayId = mPointerController->getDisplayId();
- } else {
+ } else if (mSource == AINPUT_SOURCE_MOUSE_RELATIVE) {
+ // Pointer capture mode
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
- displayId = ADISPLAY_ID_NONE;
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
}
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index bf81496..57acba5 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -111,8 +111,8 @@
if (!changes) { // first time only
// Collect all axes.
for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
- if (!(getAbsAxisUsage(abs, getDeviceContext().getDeviceClasses()) &
- INPUT_DEVICE_CLASS_JOYSTICK)) {
+ if (!(getAbsAxisUsage(abs, getDeviceContext().getDeviceClasses())
+ .test(InputDeviceClass::JOYSTICK))) {
continue; // axis must be claimed by a different device
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 15d5288..86229f9 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -142,12 +142,14 @@
hoveringIdBits.clear();
touchingIdBits.clear();
canceledIdBits.clear();
+ validIdBits.clear();
}
void CookedPointerData::copyFrom(const CookedPointerData& other) {
pointerCount = other.pointerCount;
hoveringIdBits = other.hoveringIdBits;
touchingIdBits = other.touchingIdBits;
+ validIdBits = other.validIdBits;
for (uint32_t i = 0; i < pointerCount; i++) {
pointerProperties[i].copyFrom(other.pointerProperties[i]);
@@ -288,12 +290,14 @@
const PointerProperties& pointerProperties =
mLastCookedState.cookedPointerData.pointerProperties[i];
const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
- dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
- "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, "
- "toolMinor=%0.3f, "
+ dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, dx=%0.3f, dy=%0.3f, "
+ "pressure=%0.3f, touchMajor=%0.3f, touchMinor=%0.3f, "
+ "toolMajor=%0.3f, toolMinor=%0.3f, "
"orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
"toolType=%d, isHovering=%s\n",
i, pointerProperties.id, pointerCoords.getX(), pointerCoords.getY(),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
@@ -379,6 +383,7 @@
if (!changes ||
(changes &
(InputReaderConfiguration::CHANGE_DISPLAY_INFO |
+ InputReaderConfiguration::CHANGE_POINTER_CAPTURE |
InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT |
InputReaderConfiguration::CHANGE_SHOW_TOUCHES |
InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
@@ -562,7 +567,7 @@
* 4. Otherwise, use a non-display viewport.
*/
std::optional<DisplayViewport> TouchInputMapper::findViewport() {
- if (mParameters.hasAssociatedDisplay) {
+ if (mParameters.hasAssociatedDisplay && mDeviceMode != DeviceMode::UNSCALED) {
const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
if (displayPort) {
// Find the viewport that contains the same port
@@ -620,7 +625,7 @@
// Determine device mode.
if (mParameters.deviceType == Parameters::DeviceType::POINTER &&
- mConfig.pointerGesturesEnabled) {
+ mConfig.pointerGesturesEnabled && !mConfig.pointerCapture) {
mSource = AINPUT_SOURCE_MOUSE;
mDeviceMode = DeviceMode::POINTER;
if (hasStylus()) {
@@ -1775,7 +1780,8 @@
// Pointer just went down. Check for virtual key press or off-screen touches.
uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
- if (!isPointInsideSurface(pointer.x, pointer.y)) {
+ // Exclude unscaled device for inside surface checking.
+ if (!isPointInsideSurface(pointer.x, pointer.y) && mDeviceMode != DeviceMode::UNSCALED) {
// If exactly one pointer went down, check for virtual key hit.
// Otherwise we will drop the entire stroke.
if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
@@ -2269,15 +2275,26 @@
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
}
+ // Write output relative fields if applicable.
+ uint32_t id = in.id;
+ if (mSource == AINPUT_SOURCE_TOUCHPAD &&
+ mLastCookedState.cookedPointerData.hasPointerCoordsForId(id)) {
+ const PointerCoords& p = mLastCookedState.cookedPointerData.pointerCoordsForId(id);
+ float dx = xTransformed - p.getAxisValue(AMOTION_EVENT_AXIS_X);
+ float dy = yTransformed - p.getAxisValue(AMOTION_EVENT_AXIS_Y);
+ out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, dx);
+ out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);
+ }
+
// Write output properties.
PointerProperties& properties = mCurrentCookedState.cookedPointerData.pointerProperties[i];
- uint32_t id = in.id;
properties.clear();
properties.id = id;
properties.toolType = in.toolType;
- // Write id index.
+ // Write id index and mark id as valid.
mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
+ mCurrentCookedState.cookedPointerData.validIdBits.markBit(id);
}
}
@@ -3826,9 +3843,9 @@
#if DEBUG_POINTER_ASSIGNMENT
ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, i,
- heap[i].currentPointerIndex, heap[i].lastPointerIndex, heap[i].distance);
+ for (size_t j = 0; j < heapSize; j++) {
+ ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64, j,
+ heap[j].currentPointerIndex, heap[j].lastPointerIndex, heap[j].distance);
}
#endif
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 94486a6..df6581d 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -103,7 +103,7 @@
uint32_t pointerCount;
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
- BitSet32 hoveringIdBits, touchingIdBits, canceledIdBits;
+ BitSet32 hoveringIdBits, touchingIdBits, canceledIdBits, validIdBits;
uint32_t idToIndex[MAX_POINTER_ID + 1];
CookedPointerData();
@@ -129,6 +129,8 @@
inline bool isTouching(uint32_t pointerIndex) const {
return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
}
+
+ inline bool hasPointerCoordsForId(uint32_t id) const { return validIdBits.hasBit(id); }
};
class TouchInputMapper : public InputMapper {
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 296201d..c7bb2ac 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -124,16 +124,17 @@
// This function must be called soon after the expected ANR timer starts,
// because we are also checking how much time has passed.
- void assertNotifyAnrWasCalled(std::chrono::nanoseconds timeout,
- const sp<InputApplicationHandle>& expectedApplication,
- const sp<IBinder>& expectedToken) {
- std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData;
+ void assertNotifyAnrWasCalled(
+ std::chrono::nanoseconds timeout,
+ const std::shared_ptr<InputApplicationHandle>& expectedApplication,
+ const sp<IBinder>& expectedToken) {
+ std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData;
ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
ASSERT_EQ(expectedApplication, anrData.first);
ASSERT_EQ(expectedToken, anrData.second);
}
- std::pair<sp<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
+ std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
std::chrono::nanoseconds timeout) {
const std::chrono::time_point start = std::chrono::steady_clock::now();
std::unique_lock lock(mLock);
@@ -161,7 +162,7 @@
<< std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
<< "ms instead";
}
- std::pair<sp<InputApplicationHandle>, sp<IBinder>> result =
+ std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> result =
std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
mAnrApplications.pop();
mAnrWindowTokens.pop();
@@ -189,7 +190,7 @@
std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
// ANR handling
- std::queue<sp<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
+ std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
std::condition_variable mNotifyAnr;
std::chrono::nanoseconds mAnrTimeout = 0ms;
@@ -199,7 +200,7 @@
mConfigurationChangedTime = when;
}
- std::chrono::nanoseconds notifyAnr(const sp<InputApplicationHandle>& application,
+ std::chrono::nanoseconds notifyAnr(const std::shared_ptr<InputApplicationHandle>& application,
const sp<IBinder>& windowToken,
const std::string&) override {
std::scoped_lock lock(mLock);
@@ -583,7 +584,8 @@
FakeApplicationHandle() {
mInfo.name = "Fake Application";
mInfo.token = new BBinder();
- mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo.dispatchingTimeoutMillis =
+ std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
}
virtual ~FakeApplicationHandle() {}
@@ -591,8 +593,8 @@
return true;
}
- void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
- mInfo.dispatchingTimeout = timeout;
+ void setDispatchingTimeout(std::chrono::milliseconds timeout) {
+ mInfo.dispatchingTimeoutMillis = timeout.count();
}
};
@@ -746,11 +748,11 @@
static const int32_t WIDTH = 600;
static const int32_t HEIGHT = 800;
- FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+ FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
const sp<InputDispatcher>& dispatcher, const std::string name,
- int32_t displayId, sp<IBinder> token = nullptr)
+ int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
: mName(name) {
- if (token == nullptr) {
+ if (token == std::nullopt) {
std::unique_ptr<InputChannel> serverChannel, clientChannel;
InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
@@ -761,7 +763,7 @@
inputApplicationHandle->updateInfo();
mInfo.applicationInfo = *inputApplicationHandle->getInfo();
- mInfo.token = token;
+ mInfo.token = *token;
mInfo.id = sId++;
mInfo.name = name;
mInfo.type = InputWindowInfo::Type::APPLICATION;
@@ -806,6 +808,8 @@
void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
+ void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
+
void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
}
@@ -893,8 +897,12 @@
}
void assertNoEvents() {
- ASSERT_NE(mInputReceiver, nullptr)
- << "Call 'assertNoEvents' on a window with an InputReceiver";
+ if (mInputReceiver == nullptr &&
+ mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
+ return; // Can't receive events if the window does not have input channel
+ }
+ ASSERT_NE(nullptr, mInputReceiver)
+ << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
mInputReceiver->assertNoEvents();
}
@@ -1138,7 +1146,7 @@
}
TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
ADISPLAY_ID_DEFAULT);
@@ -1160,7 +1168,7 @@
* called twice.
*/
TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 100, 100));
@@ -1183,7 +1191,7 @@
* when finding touched windows.
*/
TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 100, 100));
@@ -1202,7 +1210,7 @@
// The foreground window should receive the first touch down event.
TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
ADISPLAY_ID_DEFAULT);
sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
@@ -1219,7 +1227,7 @@
}
TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
ADISPLAY_ID_DEFAULT);
sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
@@ -1242,7 +1250,7 @@
}
TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
ADISPLAY_ID_DEFAULT);
sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
@@ -1266,7 +1274,7 @@
}
TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
ADISPLAY_ID_DEFAULT);
@@ -1293,7 +1301,7 @@
}
TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowLeft =
new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
windowLeft->setFrame(Rect(0, 0, 600, 800));
@@ -1404,7 +1412,7 @@
// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
// directly in this test.
TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
window->setFrame(Rect(0, 0, 1200, 800));
@@ -1485,7 +1493,7 @@
}
TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowLeft =
new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
@@ -1510,7 +1518,7 @@
}
TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFocus(true);
@@ -1533,7 +1541,7 @@
}
TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
@@ -1556,7 +1564,7 @@
}
TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
// Create a couple of windows
sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
@@ -1591,7 +1599,7 @@
}
TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
PointF touchPoint = {10, 10};
@@ -1647,7 +1655,7 @@
}
TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
// Create a non touch modal window that supports split touch
sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
@@ -1711,7 +1719,7 @@
}
TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
@@ -1728,7 +1736,7 @@
}
TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
@@ -1743,7 +1751,7 @@
// If a window is touchable, but does not have focus, it should receive motion events, but not keys
TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
@@ -1802,7 +1810,7 @@
// Tests for gesture monitors
TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -1818,7 +1826,7 @@
}
TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
@@ -1838,7 +1846,7 @@
}
TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -1878,7 +1886,7 @@
}
TEST_F(InputDispatcherTest, TestMoveEvent) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
@@ -1909,7 +1917,7 @@
* and the action of enabling / disabling.
*/
TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
@@ -1947,7 +1955,7 @@
}
TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
@@ -1984,7 +1992,7 @@
}
TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
@@ -2025,7 +2033,7 @@
static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
- sp<FakeApplicationHandle> mApp;
+ std::shared_ptr<FakeApplicationHandle> mApp;
sp<FakeWindowHandle> mWindow;
virtual void SetUp() override {
@@ -2039,7 +2047,7 @@
}
void setUpWindow() {
- mApp = new FakeApplicationHandle();
+ mApp = std::make_shared<FakeApplicationHandle>();
mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
mWindow->setFocus(true);
@@ -2126,7 +2134,7 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
- application1 = new FakeApplicationHandle();
+ application1 = std::make_shared<FakeApplicationHandle>();
windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
ADISPLAY_ID_DEFAULT);
@@ -2136,7 +2144,7 @@
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
windowInPrimary->consumeFocusEvent(true);
- application2 = new FakeApplicationHandle();
+ application2 = std::make_shared<FakeApplicationHandle>();
windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
SECOND_DISPLAY_ID);
// Set focus to second display window.
@@ -2152,16 +2160,16 @@
virtual void TearDown() override {
InputDispatcherTest::TearDown();
- application1.clear();
+ application1.reset();
windowInPrimary.clear();
- application2.clear();
+ application2.reset();
windowInSecondary.clear();
}
protected:
- sp<FakeApplicationHandle> application1;
+ std::shared_ptr<FakeApplicationHandle> application1;
sp<FakeWindowHandle> windowInPrimary;
- sp<FakeApplicationHandle> application2;
+ std::shared_ptr<FakeApplicationHandle> application2;
sp<FakeWindowHandle> windowInSecondary;
};
@@ -2340,7 +2348,8 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application =
+ std::make_shared<FakeApplicationHandle>();
mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
ADISPLAY_ID_DEFAULT);
mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
@@ -2434,7 +2443,8 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
- sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ std::shared_ptr<FakeApplicationHandle> application =
+ std::make_shared<FakeApplicationHandle>();
mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
ADISPLAY_ID_DEFAULT);
// Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
@@ -2636,7 +2646,7 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
- mApplication = new FakeApplicationHandle();
+ mApplication = std::make_shared<FakeApplicationHandle>();
mApplication->setDispatchingTimeout(20ms);
mWindow =
new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
@@ -2660,7 +2670,7 @@
}
protected:
- sp<FakeApplicationHandle> mApplication;
+ std::shared_ptr<FakeApplicationHandle> mApplication;
sp<FakeWindowHandle> mWindow;
static constexpr PointF WINDOW_LOCATION = {20, 20};
@@ -3019,7 +3029,7 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
- mApplication = new FakeApplicationHandle();
+ mApplication = std::make_shared<FakeApplicationHandle>();
mApplication->setDispatchingTimeout(10ms);
mUnfocusedWindow =
new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
@@ -3055,7 +3065,7 @@
}
protected:
- sp<FakeApplicationHandle> mApplication;
+ std::shared_ptr<FakeApplicationHandle> mApplication;
sp<FakeWindowHandle> mUnfocusedWindow;
sp<FakeWindowHandle> mFocusedWindow;
static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
@@ -3119,9 +3129,9 @@
tapOnFocusedWindow();
// we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
- std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData1 =
+ std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData1 =
mFakePolicy->getNotifyAnrData(10ms);
- std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData2 =
+ std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData2 =
mFakePolicy->getNotifyAnrData(0ms);
// We don't know which window will ANR first. But both of them should happen eventually.
@@ -3304,4 +3314,77 @@
mFocusedWindow->assertNoEvents();
}
+// These tests ensure we cannot send touch events to a window that's positioned behind a window
+// that has feature NO_INPUT_CHANNEL.
+// Layout:
+// Top (closest to user)
+// mNoInputWindow (above all windows)
+// mBottomWindow
+// Bottom (furthest from user)
+class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
+ virtual void SetUp() override {
+ InputDispatcherTest::SetUp();
+
+ mApplication = std::make_shared<FakeApplicationHandle>();
+ mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
+ "Window without input channel", ADISPLAY_ID_DEFAULT,
+ std::make_optional<sp<IBinder>>(nullptr) /*token*/);
+
+ mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
+ // It's perfectly valid for this window to not have an associated input channel
+
+ mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
+ ADISPLAY_ID_DEFAULT);
+ mBottomWindow->setFrame(Rect(0, 0, 100, 100));
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
+ }
+
+protected:
+ std::shared_ptr<FakeApplicationHandle> mApplication;
+ sp<FakeWindowHandle> mNoInputWindow;
+ sp<FakeWindowHandle> mBottomWindow;
+};
+
+TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
+ PointF touchedPoint = {10, 10};
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {touchedPoint});
+ mDispatcher->notifyMotion(&motionArgs);
+
+ mNoInputWindow->assertNoEvents();
+ // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
+ // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
+ // and therefore should prevent mBottomWindow from receiving touches
+ mBottomWindow->assertNoEvents();
+}
+
+/**
+ * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
+ * ensure that this window does not receive any touches, and blocks touches to windows underneath.
+ */
+TEST_F(InputDispatcherMultiWindowOcclusionTests,
+ NoInputChannelFeature_DropsTouchesWithValidChannel) {
+ mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
+ "Window with input channel and NO_INPUT_CHANNEL",
+ ADISPLAY_ID_DEFAULT);
+
+ mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
+ mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
+
+ PointF touchedPoint = {10, 10};
+
+ NotifyMotionArgs motionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {touchedPoint});
+ mDispatcher->notifyMotion(&motionArgs);
+
+ mNoInputWindow->assertNoEvents();
+ mBottomWindow->assertNoEvents();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index 02342c0..a4922fa 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -310,7 +310,9 @@
mInfo.applicationInfo.name = TestAppInfoName;
mInfo.applicationInfo.token = TestAppInfoToken;
- mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout;
+ mInfo.applicationInfo.dispatchingTimeoutMillis =
+ std::chrono::duration_cast<std::chrono::milliseconds>(TestAppInfoDispatchingTimeout)
+ .count();
InitializeInputFlinger();
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 21dd3c7..4b00ee4 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -37,6 +37,7 @@
namespace android {
using std::chrono_literals::operator""ms;
+using namespace android::flag_operators;
// Timeout for waiting for an expected event
static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms;
@@ -297,6 +298,8 @@
mConfig.defaultPointerDisplayId = pointerDisplayId;
}
+ float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
+
private:
DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
int32_t orientation, const std::string& uniqueId, std::optional<uint8_t> physicalPort,
@@ -368,7 +371,7 @@
struct Device {
InputDeviceIdentifier identifier;
- uint32_t classes;
+ Flags<InputDeviceClass> classes;
PropertyMap configuration;
KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
KeyedVector<int, bool> relativeAxes;
@@ -392,9 +395,7 @@
return OK;
}
- explicit Device(uint32_t classes) :
- classes(classes), enabled(true) {
- }
+ explicit Device(Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
};
std::mutex mLock;
@@ -414,7 +415,7 @@
FakeEventHub() { }
- void addDevice(int32_t deviceId, const std::string& name, uint32_t classes) {
+ void addDevice(int32_t deviceId, const std::string& name, Flags<InputDeviceClass> classes) {
Device* device = new Device(classes);
device->identifier.name = name;
mDevices.add(deviceId, device);
@@ -590,9 +591,9 @@
return index >= 0 ? mDevices.valueAt(index) : nullptr;
}
- virtual uint32_t getDeviceClasses(int32_t deviceId) const {
+ virtual Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const {
Device* device = getDevice(deviceId);
- return device ? device->classes : 0;
+ return device ? device->classes : Flags<InputDeviceClass>(0);
}
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const {
@@ -1384,7 +1385,7 @@
mFakePolicy.clear();
}
- void addDevice(int32_t eventHubId, const std::string& name, uint32_t classes,
+ void addDevice(int32_t eventHubId, const std::string& name, Flags<InputDeviceClass> classes,
const PropertyMap* configuration) {
mFakeEventHub->addDevice(eventHubId, name, classes);
@@ -1409,8 +1410,8 @@
}
FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
- const std::string& name, uint32_t classes,
- uint32_t sources,
+ const std::string& name,
+ Flags<InputDeviceClass> classes, uint32_t sources,
const PropertyMap* configuration) {
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(eventHubId, sources);
@@ -1421,10 +1422,9 @@
};
TEST_F(InputReaderTest, GetInputDevices) {
- ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard",
- INPUT_DEVICE_CLASS_KEYBOARD, nullptr));
- ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored",
- 0, nullptr)); // no classes so device will be ignored
+ ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", Flags<InputDeviceClass>(0),
+ nullptr)); // no classes so device will be ignored
std::vector<InputDeviceInfo> inputDevices;
mReader->getInputDevices(inputDevices);
@@ -1447,7 +1447,7 @@
TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -1484,7 +1484,7 @@
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1517,7 +1517,7 @@
TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1550,7 +1550,7 @@
TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1583,7 +1583,7 @@
TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1625,7 +1625,7 @@
TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
constexpr int32_t eventHubId = 1;
- addDevice(eventHubId, "ignored", INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
+ addDevice(eventHubId, "ignored", InputDeviceClass::KEYBOARD, nullptr);
NotifyConfigurationChangedArgs args;
@@ -1635,7 +1635,7 @@
TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1656,7 +1656,7 @@
TEST_F(InputReaderTest, DeviceReset_RandomId) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -1689,7 +1689,7 @@
TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
constexpr int32_t deviceId = 1;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -1704,7 +1704,7 @@
TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "USB1";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
@@ -2024,7 +2024,7 @@
static const int32_t DEVICE_ID;
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const uint32_t DEVICE_CLASSES;
+ static const Flags<InputDeviceClass> DEVICE_CLASSES;
static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
@@ -2040,7 +2040,7 @@
mFakeListener = new TestInputListener();
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
- mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, 0);
+ mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, Flags<InputDeviceClass>(0));
InputDeviceIdentifier identifier;
identifier.name = DEVICE_NAME;
identifier.location = DEVICE_LOCATION;
@@ -2061,14 +2061,14 @@
const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
-const uint32_t InputDeviceTest::DEVICE_CLASSES = INPUT_DEVICE_CLASS_KEYBOARD
- | INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_JOYSTICK;
+const Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
+ InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
const int32_t InputDeviceTest::EVENTHUB_ID = 1;
TEST_F(InputDeviceTest, ImmutableProperties) {
ASSERT_EQ(DEVICE_ID, mDevice->getId());
ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
- ASSERT_EQ(0U, mDevice->getClasses());
+ ASSERT_EQ(Flags<InputDeviceClass>(0), mDevice->getClasses());
}
TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
@@ -2263,7 +2263,7 @@
static const int32_t DEVICE_ID;
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const uint32_t DEVICE_CLASSES;
+ static const Flags<InputDeviceClass> DEVICE_CLASSES;
static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
@@ -2272,7 +2272,7 @@
FakeInputReaderContext* mFakeContext;
InputDevice* mDevice;
- virtual void SetUp(uint32_t classes) {
+ virtual void SetUp(Flags<InputDeviceClass> classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
@@ -2377,7 +2377,8 @@
const int32_t InputMapperTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t InputMapperTest::DEVICE_GENERATION = 2;
const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0;
-const uint32_t InputMapperTest::DEVICE_CLASSES = 0; // not needed for current tests
+const Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
+ Flags<InputDeviceClass>(0); // not needed for current tests
const int32_t InputMapperTest::EVENTHUB_ID = 1;
// --- SwitchInputMapperTest ---
@@ -2882,7 +2883,8 @@
std::unique_ptr<InputDevice> device2 =
std::make_unique<InputDevice>(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
identifier);
- mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME, 0 /*classes*/);
+ mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME,
+ Flags<InputDeviceClass>(0) /*classes*/);
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
@@ -2950,7 +2952,7 @@
class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest {
protected:
virtual void SetUp() override {
- InputMapperTest::SetUp(DEVICE_CLASSES | INPUT_DEVICE_CLASS_EXTERNAL);
+ InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL);
}
};
@@ -6863,7 +6865,8 @@
std::unique_ptr<InputDevice> device2 =
std::make_unique<InputDevice>(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
identifier);
- mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME, 0 /*classes*/);
+ mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME,
+ Flags<InputDeviceClass>(0) /*classes*/);
mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
0 /*flat*/, 0 /*fuzz*/);
mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
@@ -7376,7 +7379,7 @@
class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
protected:
virtual void SetUp() override {
- InputMapperTest::SetUp(DEVICE_CLASSES | INPUT_DEVICE_CLASS_EXTERNAL);
+ InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL);
}
};
@@ -7533,4 +7536,209 @@
constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4;
processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchpadCapture) {
+ // we need a pointer controller for mouse mode of touchpad (start pointer at 0,0)
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+ fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
+ fakePointerController->setPosition(0, 0);
+ fakePointerController->setButtonState(0);
+
+ // prepare device and capture
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
+ mFakePolicy->setPointerCapture(true);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // captured touchpad should be a touchpad source
+ NotifyDeviceResetArgs resetArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+
+ // run captured pointer tests - note that this is unscaled, so input listener events should be
+ // identical to what the hardware sends (accounting for any
+ // calibration).
+ // FINGER 0 DOWN
+ processSlot(mapper, 0);
+ processId(mapper, 1);
+ processPosition(mapper, 100 + RAW_X_MIN, 100 + RAW_Y_MIN);
+ processKey(mapper, BTN_TOUCH, 1);
+ processSync(mapper);
+
+ // expect coord[0] to contain initial location of touch 0
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(1U, args.pointerCount);
+ ASSERT_EQ(0, args.pointerProperties[0].id);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, args.source);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 1 DOWN
+ processSlot(mapper, 1);
+ processId(mapper, 2);
+ processPosition(mapper, 560 + RAW_X_MIN, 154 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain previous location, coord[1] to contain new touch 1 location
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ args.action);
+ ASSERT_EQ(2U, args.pointerCount);
+ ASSERT_EQ(0, args.pointerProperties[0].id);
+ ASSERT_EQ(1, args.pointerProperties[1].id);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[1], 560, 154, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 1 MOVE
+ processPosition(mapper, 540 + RAW_X_MIN, 690 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain previous location, coord[1] to contain new touch 1 location
+ // from move
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[1], 540, 690, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 0 MOVE
+ processSlot(mapper, 0);
+ processPosition(mapper, 50 + RAW_X_MIN, 800 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain new touch 0 location, coord[1] to contain previous location
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 50, 800, 1, 0, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[1], 540, 690, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // BUTTON DOWN
+ processKey(mapper, BTN_LEFT, 1);
+ processSync(mapper);
+
+ // touchinputmapper design sends a move before button press
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
+
+ // BUTTON UP
+ processKey(mapper, BTN_LEFT, 0);
+ processSync(mapper);
+
+ // touchinputmapper design sends a move after button release
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+
+ // FINGER 0 UP
+ processId(mapper, -1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | 0x0000, args.action);
+
+ // FINGER 1 MOVE
+ processSlot(mapper, 1);
+ processPosition(mapper, 320 + RAW_X_MIN, 900 + RAW_Y_MIN);
+ processSync(mapper);
+
+ // expect coord[0] to contain new location of touch 1, and properties[0].id to contain 1
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_EQ(1U, args.pointerCount);
+ ASSERT_EQ(1, args.pointerProperties[0].id);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 320, 900, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 1 UP
+ processId(mapper, -1);
+ processKey(mapper, BTN_TOUCH, 0);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+
+ // non captured touchpad should be a mouse source
+ mFakePolicy->setPointerCapture(false);
+ configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_UnCapturedTouchpadPointer) {
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+ fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
+ fakePointerController->setPosition(0, 0);
+ fakePointerController->setButtonState(0);
+
+ // prepare device and capture
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ // run uncaptured pointer tests - pushes out generic events
+ // FINGER 0 DOWN
+ processId(mapper, 3);
+ processPosition(mapper, 100, 100);
+ processKey(mapper, BTN_TOUCH, 1);
+ processSync(mapper);
+
+ // start at (100,100), cursor should be at (0,0) * scale
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(
+ assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ // FINGER 0 MOVE
+ processPosition(mapper, 200, 200);
+ processSync(mapper);
+
+ // compute scaling to help with touch position checking
+ float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
+ float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ float scale =
+ mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
+
+ // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
+ 0, 0, 0, 0, 0, 0, 0));
+}
+
+TEST_F(MultiTouchInputMapperTest, WhenCapturedAndNotCaptured_GetSources) {
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
+ mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ mFakePolicy->setPointerCapture(false);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // uncaptured touchpad should be a pointer device
+ ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
+
+ // captured touchpad should be a touchpad device
+ mFakePolicy->setPointerCapture(true);
+ configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
+}
+
} // namespace android
diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp
index 95f8623..4a711ca 100644
--- a/services/powermanager/PowerHalWrapper.cpp
+++ b/services/powermanager/PowerHalWrapper.cpp
@@ -29,12 +29,20 @@
// -------------------------------------------------------------------------------------------------
inline HalResult toHalResult(const binder::Status& result) {
- return result.isOk() ? HalResult::SUCCESSFUL : HalResult::FAILED;
+ if (result.isOk()) {
+ return HalResult::SUCCESSFUL;
+ }
+ ALOGE("Power HAL request failed: %s", result.toString8().c_str());
+ return HalResult::FAILED;
}
template <typename T>
inline HalResult toHalResult(const hardware::Return<T>& result) {
- return result.isOk() ? HalResult::SUCCESSFUL : HalResult::FAILED;
+ if (result.isOk()) {
+ return HalResult::SUCCESSFUL;
+ }
+ ALOGE("Power HAL request failed: %s", result.description().c_str());
+ return HalResult::FAILED;
}
// -------------------------------------------------------------------------------------------------
@@ -117,8 +125,8 @@
bool isSupported = false;
auto isSupportedRet = mHandle->isBoostSupported(boost, &isSupported);
if (!isSupportedRet.isOk()) {
- ALOGV("Skipped setBoost %s because Power HAL is not available to check support",
- toString(boost).c_str());
+ ALOGE("Skipped setBoost %s because check support failed with: %s",
+ toString(boost).c_str(), isSupportedRet.toString8().c_str());
return HalResult::FAILED;
}
@@ -148,8 +156,8 @@
bool isSupported = false;
auto isSupportedRet = mHandle->isModeSupported(mode, &isSupported);
if (!isSupportedRet.isOk()) {
- ALOGV("Skipped setMode %s because Power HAL is not available to check support",
- toString(mode).c_str());
+ ALOGE("Skipped setMode %s because check support failed with: %s",
+ toString(mode).c_str(), isSupportedRet.toString8().c_str());
return HalResult::FAILED;
}
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
index 5975269..4c5d508 100644
--- a/services/powermanager/benchmarks/Android.bp
+++ b/services/powermanager/benchmarks/Android.bp
@@ -31,6 +31,9 @@
"android.hardware.power@1.1",
"android.hardware.power-cpp",
],
+ static_libs: [
+ "libtestUtil",
+ ],
cflags: [
"-Wall",
"-Werror",
diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
index a6dad51..1004828 100644
--- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -19,50 +19,78 @@
#include <android/hardware/power/Boost.h>
#include <android/hardware/power/IPower.h>
#include <android/hardware/power/Mode.h>
-
#include <benchmark/benchmark.h>
-
#include <binder/IServiceManager.h>
+#include <testUtil.h>
+#include <chrono>
using android::hardware::power::Boost;
using android::hardware::power::IPower;
using android::hardware::power::Mode;
+using std::chrono::microseconds;
using namespace android;
+using namespace std::chrono_literals;
+
+// Values from Boost.aidl and Mode.aidl.
+static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
+static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
+static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
+static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
+
+// Delay between oneway method calls to avoid overflowing the binder buffers.
+static constexpr microseconds ONEWAY_API_DELAY = 100us;
template <class R, class... Args0, class... Args1>
-static void runBenchmark(benchmark::State& state, R (IPower::*fn)(Args0...), Args1&&... args1) {
+static void runBenchmark(benchmark::State& state, microseconds delay, R (IPower::*fn)(Args0...),
+ Args1&&... args1) {
sp<IPower> hal = waitForVintfService<IPower>();
if (hal == nullptr) {
- ALOGI("Power HAL AIDL not available, skipping test...");
+ ALOGI("Power HAL not available, skipping test...");
+ return;
+ }
+
+ binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...);
+ if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
+ ALOGI("Power HAL does not support this operation, skipping test...");
return;
}
while (state.KeepRunning()) {
- (*hal.*fn)(std::forward<Args1>(args1)...);
+ ret = (*hal.*fn)(std::forward<Args1>(args1)...);
+ state.PauseTiming();
+ if (!ret.isOk()) state.SkipWithError(ret.toString8().c_str());
+ if (delay > 0us) {
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ }
+ state.ResumeTiming();
}
}
static void BM_PowerHalAidlBenchmarks_isBoostSupported(benchmark::State& state) {
bool isSupported;
- runBenchmark(state, &IPower::isBoostSupported, Boost::INTERACTION, &isSupported);
+ Boost boost = static_cast<Boost>(state.range(0));
+ runBenchmark(state, 0us, &IPower::isBoostSupported, boost, &isSupported);
}
static void BM_PowerHalAidlBenchmarks_isModeSupported(benchmark::State& state) {
bool isSupported;
- runBenchmark(state, &IPower::isModeSupported, Mode::INTERACTIVE, &isSupported);
+ Mode mode = static_cast<Mode>(state.range(0));
+ runBenchmark(state, 0us, &IPower::isModeSupported, mode, &isSupported);
}
static void BM_PowerHalAidlBenchmarks_setBoost(benchmark::State& state) {
- runBenchmark(state, &IPower::setBoost, Boost::INTERACTION, 0);
+ Boost boost = static_cast<Boost>(state.range(0));
+ runBenchmark(state, ONEWAY_API_DELAY, &IPower::setBoost, boost, 1);
}
static void BM_PowerHalAidlBenchmarks_setMode(benchmark::State& state) {
- runBenchmark(state, &IPower::setMode, Mode::INTERACTIVE, false);
+ Mode mode = static_cast<Mode>(state.range(0));
+ runBenchmark(state, ONEWAY_API_DELAY, &IPower::setMode, mode, false);
}
-BENCHMARK(BM_PowerHalAidlBenchmarks_isBoostSupported);
-BENCHMARK(BM_PowerHalAidlBenchmarks_isModeSupported);
-BENCHMARK(BM_PowerHalAidlBenchmarks_setBoost);
-BENCHMARK(BM_PowerHalAidlBenchmarks_setMode);
+BENCHMARK(BM_PowerHalAidlBenchmarks_isBoostSupported)->DenseRange(FIRST_BOOST, LAST_BOOST, 1);
+BENCHMARK(BM_PowerHalAidlBenchmarks_isModeSupported)->DenseRange(FIRST_MODE, LAST_MODE, 1);
+BENCHMARK(BM_PowerHalAidlBenchmarks_setBoost)->DenseRange(FIRST_BOOST, LAST_BOOST, 1);
+BENCHMARK(BM_PowerHalAidlBenchmarks_setMode)->DenseRange(FIRST_MODE, LAST_MODE, 1);
diff --git a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
index a3a1f4e..598080b 100644
--- a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
@@ -18,16 +18,58 @@
#include <android/hardware/power/Boost.h>
#include <android/hardware/power/Mode.h>
-
#include <benchmark/benchmark.h>
-
#include <powermanager/PowerHalController.h>
+#include <testUtil.h>
+#include <chrono>
using android::hardware::power::Boost;
using android::hardware::power::Mode;
+using android::power::HalResult;
using android::power::PowerHalController;
using namespace android;
+using namespace std::chrono_literals;
+
+// Values from Boost.aidl and Mode.aidl.
+static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
+static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
+static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
+static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
+
+// Delay between oneway method calls to avoid overflowing the binder buffers.
+static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us;
+
+template <class... Args0, class... Args1>
+static void runBenchmark(benchmark::State& state, HalResult (PowerHalController::*fn)(Args0...),
+ Args1&&... args1) {
+ while (state.KeepRunning()) {
+ PowerHalController controller;
+ HalResult ret = (controller.*fn)(std::forward<Args1>(args1)...);
+ state.PauseTiming();
+ if (ret == HalResult::FAILED) state.SkipWithError("Power HAL request failed");
+ state.ResumeTiming();
+ }
+}
+
+template <class... Args0, class... Args1>
+static void runCachedBenchmark(benchmark::State& state,
+ HalResult (PowerHalController::*fn)(Args0...), Args1&&... args1) {
+ PowerHalController controller;
+ // First call out of test, to cache HAL service and isSupported result.
+ (controller.*fn)(std::forward<Args1>(args1)...);
+
+ while (state.KeepRunning()) {
+ HalResult ret = (controller.*fn)(std::forward<Args1>(args1)...);
+ state.PauseTiming();
+ if (ret == HalResult::FAILED) {
+ state.SkipWithError("Power HAL request failed");
+ }
+ testDelaySpin(
+ std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
+ state.ResumeTiming();
+ }
+}
static void BM_PowerHalControllerBenchmarks_init(benchmark::State& state) {
while (state.KeepRunning()) {
@@ -47,42 +89,28 @@
}
static void BM_PowerHalControllerBenchmarks_setBoost(benchmark::State& state) {
- while (state.KeepRunning()) {
- PowerHalController controller;
- controller.setBoost(Boost::INTERACTION, 0);
- }
+ Boost boost = static_cast<Boost>(state.range(0));
+ runBenchmark(state, &PowerHalController::setBoost, boost, 0);
}
static void BM_PowerHalControllerBenchmarks_setBoostCached(benchmark::State& state) {
- PowerHalController controller;
- // First call out of test, to cache supported boost.
- controller.setBoost(Boost::INTERACTION, 0);
-
- while (state.KeepRunning()) {
- controller.setBoost(Boost::INTERACTION, 0);
- }
+ Boost boost = static_cast<Boost>(state.range(0));
+ runCachedBenchmark(state, &PowerHalController::setBoost, boost, 0);
}
static void BM_PowerHalControllerBenchmarks_setMode(benchmark::State& state) {
- while (state.KeepRunning()) {
- PowerHalController controller;
- controller.setMode(Mode::INTERACTIVE, false);
- }
+ Mode mode = static_cast<Mode>(state.range(0));
+ runBenchmark(state, &PowerHalController::setMode, mode, false);
}
static void BM_PowerHalControllerBenchmarks_setModeCached(benchmark::State& state) {
- PowerHalController controller;
- // First call out of test, to cache supported mode.
- controller.setMode(Mode::INTERACTIVE, false);
-
- while (state.KeepRunning()) {
- controller.setMode(Mode::INTERACTIVE, false);
- }
+ Mode mode = static_cast<Mode>(state.range(0));
+ runCachedBenchmark(state, &PowerHalController::setMode, mode, false);
}
BENCHMARK(BM_PowerHalControllerBenchmarks_init);
BENCHMARK(BM_PowerHalControllerBenchmarks_initCached);
-BENCHMARK(BM_PowerHalControllerBenchmarks_setBoost);
-BENCHMARK(BM_PowerHalControllerBenchmarks_setBoostCached);
-BENCHMARK(BM_PowerHalControllerBenchmarks_setMode);
-BENCHMARK(BM_PowerHalControllerBenchmarks_setModeCached);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setBoost)->DenseRange(FIRST_BOOST, LAST_BOOST, 1);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setBoostCached)->DenseRange(FIRST_BOOST, LAST_BOOST, 1);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setMode)->DenseRange(FIRST_MODE, LAST_MODE, 1);
+BENCHMARK(BM_PowerHalControllerBenchmarks_setModeCached)->DenseRange(FIRST_MODE, LAST_MODE, 1);
diff --git a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
index 5542ac4..97e026b 100644
--- a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
@@ -20,23 +20,34 @@
#include <android/hardware/power/Boost.h>
#include <android/hardware/power/IPower.h>
#include <android/hardware/power/Mode.h>
-
#include <benchmark/benchmark.h>
-
#include <hardware/power.h>
#include <hardware_legacy/power.h>
+#include <testUtil.h>
+#include <chrono>
+using android::hardware::Return;
using android::hardware::power::Boost;
using android::hardware::power::Mode;
using android::hardware::power::V1_0::Feature;
using android::hardware::power::V1_0::PowerHint;
+using std::chrono::microseconds;
using IPower1_0 = android::hardware::power::V1_0::IPower;
using IPower1_1 = android::hardware::power::V1_1::IPower;
using namespace android;
+using namespace std::chrono_literals;
+
+// Values from types.hal from versions 1.0 to 1.3.
+static constexpr int64_t FIRST_POWER_HINT = static_cast<int64_t>(PowerHint::VSYNC);
+static constexpr int64_t LAST_POWER_HINT = static_cast<int64_t>(PowerHint::LAUNCH);
+
+// Delay between oneway method calls to avoid overflowing the binder buffers.
+static constexpr microseconds ONEWAY_API_DELAY = 100us;
template <class R, class I, class... Args0, class... Args1>
-static void runBenchmark(benchmark::State& state, R (I::*fn)(Args0...), Args1&&... args1) {
+static void runBenchmark(benchmark::State& state, microseconds delay, Return<R> (I::*fn)(Args0...),
+ Args1&&... args1) {
sp<I> hal = I::getService();
if (hal == nullptr) {
@@ -45,27 +56,37 @@
}
while (state.KeepRunning()) {
- (*hal.*fn)(std::forward<Args1>(args1)...);
+ Return<R> ret = (*hal.*fn)(std::forward<Args1>(args1)...);
+ state.PauseTiming();
+ if (!ret.isOk()) state.SkipWithError(ret.description().c_str());
+ if (delay > 0us) {
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ }
+ state.ResumeTiming();
}
}
static void BM_PowerHalHidlBenchmarks_setFeature(benchmark::State& state) {
- runBenchmark(state, &IPower1_0::setFeature, Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE, false);
+ runBenchmark(state, 0us, &IPower1_0::setFeature, Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE,
+ false);
}
static void BM_PowerHalHidlBenchmarks_setInteractive(benchmark::State& state) {
- runBenchmark(state, &IPower1_0::setInteractive, false);
+ runBenchmark(state, 0us, &IPower1_0::setInteractive, false);
}
static void BM_PowerHalHidlBenchmarks_powerHint(benchmark::State& state) {
- runBenchmark(state, &IPower1_0::powerHint, PowerHint::INTERACTION, 0);
+ PowerHint powerHint = static_cast<PowerHint>(state.range(0));
+ runBenchmark(state, 0us, &IPower1_0::powerHint, powerHint, 0);
}
static void BM_PowerHalHidlBenchmarks_powerHintAsync(benchmark::State& state) {
- runBenchmark(state, &IPower1_1::powerHintAsync, PowerHint::INTERACTION, 0);
+ PowerHint powerHint = static_cast<PowerHint>(state.range(0));
+ runBenchmark(state, ONEWAY_API_DELAY, &IPower1_1::powerHintAsync, powerHint, 0);
}
BENCHMARK(BM_PowerHalHidlBenchmarks_setFeature);
BENCHMARK(BM_PowerHalHidlBenchmarks_setInteractive);
-BENCHMARK(BM_PowerHalHidlBenchmarks_powerHint);
-BENCHMARK(BM_PowerHalHidlBenchmarks_powerHintAsync);
+BENCHMARK(BM_PowerHalHidlBenchmarks_powerHint)->DenseRange(FIRST_POWER_HINT, LAST_POWER_HINT, 1);
+BENCHMARK(BM_PowerHalHidlBenchmarks_powerHintAsync)
+ ->DenseRange(FIRST_POWER_HINT, LAST_POWER_HINT, 1);
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 804a3c3..c55e9df 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -162,7 +162,6 @@
"RenderArea.cpp",
"Scheduler/DispSync.cpp",
"Scheduler/DispSyncSource.cpp",
- "Scheduler/EventControlThread.cpp",
"Scheduler/EventThread.cpp",
"Scheduler/OneShotTimer.cpp",
"Scheduler/LayerHistory.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index baf5258..26299e9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -164,8 +164,8 @@
// Sets the projection state to use
virtual void setProjection(const ui::Transform&, uint32_t orientation, const Rect& frame,
- const Rect& viewport, const Rect& sourceClip,
- const Rect& destinationClip, bool needsFiltering) = 0;
+ const Rect& viewport, const Rect& destinationClip,
+ bool needsFiltering) = 0;
// Sets the bounds to use
virtual void setBounds(const ui::Size&) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 6f25e63..0ac2545 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -39,7 +39,7 @@
std::optional<DisplayId> getDisplayId() const override;
void setCompositionEnabled(bool) override;
void setProjection(const ui::Transform&, uint32_t orientation, const Rect& frame,
- const Rect& viewport, const Rect& sourceClip, const Rect& destinationClip,
+ const Rect& viewport, const Rect& destinationClip,
bool needsFiltering) override;
void setBounds(const ui::Size&) override;
void setLayerStackFilter(uint32_t layerStackId, bool isInternal) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 66ed2b6..7120a48 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -79,9 +79,6 @@
// The logical space user viewport rectangle
Rect viewport;
- // The physical space source clip rectangle
- Rect sourceClip;
-
// The physical space destination clip rectangle
Rect destinationClip;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 4661c5d..c4dff73 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -36,9 +36,8 @@
MOCK_CONST_METHOD0(getDisplayId, std::optional<DisplayId>());
MOCK_METHOD1(setCompositionEnabled, void(bool));
- MOCK_METHOD7(setProjection,
- void(const ui::Transform&, uint32_t, const Rect&, const Rect&, const Rect&,
- const Rect&, bool));
+ MOCK_METHOD6(setProjection,
+ void(const ui::Transform&, uint32_t, const Rect&, const Rect&, const Rect&, bool));
MOCK_METHOD1(setBounds, void(const ui::Size&));
MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool));
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index b07c904..09b3dd7 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -106,12 +106,10 @@
}
void Output::setProjection(const ui::Transform& transform, uint32_t orientation, const Rect& frame,
- const Rect& viewport, const Rect& sourceClip,
- const Rect& destinationClip, bool needsFiltering) {
+ const Rect& viewport, const Rect& destinationClip, bool needsFiltering) {
auto& outputState = editState();
outputState.transform = transform;
outputState.orientation = orientation;
- outputState.sourceClip = sourceClip;
outputState.destinationClip = destinationClip;
outputState.frame = frame;
outputState.viewport = viewport;
@@ -863,7 +861,7 @@
renderengine::DisplaySettings clientCompositionDisplay;
clientCompositionDisplay.physicalDisplay = outputState.destinationClip;
- clientCompositionDisplay.clip = outputState.sourceClip;
+ clientCompositionDisplay.clip = outputState.viewport;
clientCompositionDisplay.orientation = outputState.orientation;
clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
? outputState.dataspace
@@ -951,7 +949,7 @@
const bool useIdentityTransform = false;
bool firstLayer = true;
// Used when a layer clears part of the buffer.
- Region dummyRegion;
+ Region stubRegion;
for (auto* layer : getOutputLayersOrderedByZ()) {
const auto& layerState = layer->getState();
@@ -990,7 +988,7 @@
layer->needsFiltering() || outputState.needsFiltering,
outputState.isSecure,
supportsProtectedContent,
- clientComposition ? clearRegion : dummyRegion,
+ clientComposition ? clearRegion : stubRegion,
outputState.viewport,
outputDataspace,
realContentIsVisible,
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
index 4835aef..f3b2da1 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
@@ -41,7 +41,6 @@
dumpVal(out, "bounds", bounds);
dumpVal(out, "frame", frame);
dumpVal(out, "viewport", viewport);
- dumpVal(out, "sourceClip", sourceClip);
dumpVal(out, "destinationClip", destinationClip);
dumpVal(out, "needsFiltering", needsFiltering);
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 09f37fb..378c050 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -56,8 +56,9 @@
using testing::SetArgPointee;
using testing::StrictMock;
-constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
-constexpr DisplayId VIRTUAL_DISPLAY_ID = DisplayId{43};
+constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId{42};
+// TODO(b/160679868) Use VirtualDisplayId
+constexpr PhysicalDisplayId VIRTUAL_DISPLAY_ID = PhysicalDisplayId{43};
constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080;
constexpr int32_t DEFAULT_LAYER_STACK = 123;
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 75a4fec..1dd5df4 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -46,7 +46,7 @@
MOCK_METHOD3(allocateVirtualDisplay,
std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
- MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, DisplayId));
+ MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId));
MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
MOCK_METHOD3(getDeviceCompositionChanges,
@@ -107,8 +107,8 @@
MOCK_CONST_METHOD1(getHwcDisplayId, std::optional<hal::HWDisplayId>(int32_t));
MOCK_CONST_METHOD0(getInternalHwcDisplayId, std::optional<hal::HWDisplayId>());
MOCK_CONST_METHOD0(getExternalHwcDisplayId, std::optional<hal::HWDisplayId>());
- MOCK_CONST_METHOD1(toPhysicalDisplayId, std::optional<DisplayId>(hal::HWDisplayId));
- MOCK_CONST_METHOD1(fromPhysicalDisplayId, std::optional<hal::HWDisplayId>(DisplayId));
+ MOCK_CONST_METHOD1(toPhysicalDisplayId, std::optional<PhysicalDisplayId>(hal::HWDisplayId));
+ MOCK_CONST_METHOD1(fromPhysicalDisplayId, std::optional<hal::HWDisplayId>(PhysicalDisplayId));
};
} // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 59ed72e..6ba06a6 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -240,18 +240,16 @@
const int32_t orientation = 123;
const Rect frame{1, 2, 3, 4};
const Rect viewport{5, 6, 7, 8};
- const Rect sourceClip{9, 10, 11, 12};
const Rect destinationClip{13, 14, 15, 16};
const bool needsFiltering = true;
- mOutput->setProjection(transform, orientation, frame, viewport, sourceClip, destinationClip,
+ mOutput->setProjection(transform, orientation, frame, viewport, destinationClip,
needsFiltering);
EXPECT_THAT(mOutput->getState().transform, transform);
EXPECT_EQ(orientation, mOutput->getState().orientation);
EXPECT_EQ(frame, mOutput->getState().frame);
EXPECT_EQ(viewport, mOutput->getState().viewport);
- EXPECT_EQ(sourceClip, mOutput->getState().sourceClip);
EXPECT_EQ(destinationClip, mOutput->getState().destinationClip);
EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
}
@@ -2787,7 +2785,6 @@
mOutput.mState.frame = kDefaultOutputFrame;
mOutput.mState.viewport = kDefaultOutputViewport;
- mOutput.mState.sourceClip = kDefaultOutputSourceClip;
mOutput.mState.destinationClip = kDefaultOutputDestinationClip;
mOutput.mState.transform = ui::Transform{kDefaultOutputOrientation};
mOutput.mState.orientation = kDefaultOutputOrientation;
@@ -2834,7 +2831,6 @@
static const Rect kDefaultOutputFrame;
static const Rect kDefaultOutputViewport;
- static const Rect kDefaultOutputSourceClip;
static const Rect kDefaultOutputDestinationClip;
static const mat4 kDefaultColorTransformMat;
@@ -2856,7 +2852,6 @@
const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
-const Rect OutputComposeSurfacesTest::kDefaultOutputSourceClip{1009, 1010, 1011, 1012};
const Rect OutputComposeSurfacesTest::kDefaultOutputDestinationClip{1013, 1014, 1015, 1016};
const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5f};
const compositionengine::CompositionRefreshArgs OutputComposeSurfacesTest::kDefaultRefreshArgs;
@@ -3122,7 +3117,7 @@
verify().ifMixedCompositionIs(true)
.andIfUsesHdr(true)
.andIfSkipColorTransform(false)
- .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
+ .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
Region::INVALID_REGION, kDefaultOutputOrientation})
.execute()
@@ -3133,7 +3128,7 @@
verify().ifMixedCompositionIs(true)
.andIfUsesHdr(false)
.andIfSkipColorTransform(false)
- .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
+ .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
Region::INVALID_REGION, kDefaultOutputOrientation})
.execute()
@@ -3144,7 +3139,7 @@
verify().ifMixedCompositionIs(false)
.andIfUsesHdr(true)
.andIfSkipColorTransform(false)
- .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
+ .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
kDefaultMaxLuminance, kDefaultOutputDataspace,
kDefaultColorTransformMat, Region::INVALID_REGION,
kDefaultOutputOrientation})
@@ -3156,7 +3151,7 @@
verify().ifMixedCompositionIs(false)
.andIfUsesHdr(false)
.andIfSkipColorTransform(false)
- .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
+ .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
kDefaultMaxLuminance, kDefaultOutputDataspace,
kDefaultColorTransformMat, Region::INVALID_REGION,
kDefaultOutputOrientation})
@@ -3169,7 +3164,7 @@
verify().ifMixedCompositionIs(false)
.andIfUsesHdr(true)
.andIfSkipColorTransform(true)
- .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
+ .thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputViewport,
kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
Region::INVALID_REGION, kDefaultOutputOrientation})
.execute()
@@ -3416,7 +3411,6 @@
GenerateClientCompositionRequestsTest_ThreeLayers() {
mOutput.mState.frame = kDisplayFrame;
mOutput.mState.viewport = kDisplayViewport;
- mOutput.mState.sourceClip = kDisplaySourceClip;
mOutput.mState.destinationClip = kDisplayDestinationClip;
mOutput.mState.transform = ui::Transform{kDisplayOrientation};
mOutput.mState.orientation = kDisplayOrientation;
@@ -3448,7 +3442,6 @@
static const Rect kDisplayFrame;
static const Rect kDisplayViewport;
- static const Rect kDisplaySourceClip;
static const Rect kDisplayDestinationClip;
std::array<Layer, 3> mLayers;
@@ -3456,7 +3449,6 @@
const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayFrame(0, 0, 100, 200);
const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayViewport(0, 0, 101, 201);
-const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplaySourceClip(0, 0, 102, 202);
const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayDestinationClip(0, 0, 103,
203);
@@ -3583,15 +3575,15 @@
mLayers[1].mLayerFEState.isOpaque = true;
mLayers[2].mLayerFEState.isOpaque = true;
Region accumClearRegion(Rect(10, 11, 12, 13));
- Region dummyRegion;
+ Region stubRegion;
compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
Region(kDisplayFrame),
- false, /* identity transform */
- false, /* needs filtering */
- false, /* secure */
- false, /* supports protected content */
- dummyRegion, /* clear region */
+ false, /* identity transform */
+ false, /* needs filtering */
+ false, /* secure */
+ false, /* supports protected content */
+ stubRegion, /* clear region */
kDisplayViewport,
kDisplayDataspace,
false /* realContentIsVisible */,
@@ -3945,14 +3937,12 @@
const Rect kPortraitFrame(0, 0, 1000, 2000);
const Rect kPortraitViewport(0, 0, 2000, 1000);
- const Rect kPortraitSourceClip(0, 0, 1000, 2000);
const Rect kPortraitDestinationClip(0, 0, 1000, 2000);
const uint32_t kPortraitOrientation = TR_ROT_90;
constexpr ui::Dataspace kOutputDataspace = ui::Dataspace::DISPLAY_P3;
mOutput.mState.frame = kPortraitFrame;
mOutput.mState.viewport = kPortraitViewport;
- mOutput.mState.sourceClip = kPortraitSourceClip;
mOutput.mState.destinationClip = kPortraitDestinationClip;
mOutput.mState.transform = ui::Transform{kPortraitOrientation};
mOutput.mState.orientation = kPortraitOrientation;
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index fd47e45..519cc57 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -33,7 +33,7 @@
constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080;
-constexpr std::optional<DisplayId> DEFAULT_DISPLAY_ID = std::make_optional(DisplayId{123u});
+constexpr std::optional<DisplayId> DEFAULT_DISPLAY_ID = {PhysicalDisplayId(123u)};
const std::string DEFAULT_DISPLAY_NAME = "Mock Display";
using testing::_;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9aa274b..a4fc833 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -226,7 +226,6 @@
const bool needsFiltering =
(!globalTransform.preserveRects() || (type >= ui::Transform::SCALE));
- const Rect& sourceClip = viewport;
Rect destinationClip = globalTransform.transform(viewport);
if (destinationClip.isEmpty()) {
destinationClip = displayBounds;
@@ -244,7 +243,7 @@
}
getCompositionDisplay()->setProjection(globalTransform, transformOrientation, frame, viewport,
- sourceClip, destinationClip, needsFiltering);
+ destinationClip, needsFiltering);
}
ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() {
@@ -324,10 +323,6 @@
return mCompositionDisplay->getState().frame;
}
-const Rect& DisplayDevice::getSourceClip() const {
- return mCompositionDisplay->getState().sourceClip;
-}
-
bool DisplayDevice::hasWideColorGamut() const {
return mCompositionDisplay->getDisplayColorProfile()->hasWideColorGamut();
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 576488c..1319679 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -101,7 +101,6 @@
const ui::Transform& getTransform() const;
const Rect& getViewport() const;
const Rect& getFrame() const;
- const Rect& getSourceClip() const;
bool needsFiltering() const;
ui::LayerStack getLayerStack() const;
@@ -194,7 +193,7 @@
struct DisplayDeviceState {
struct Physical {
- DisplayId id;
+ PhysicalDisplayId id;
DisplayConnectionType type;
hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
std::optional<DeviceProductInfo> deviceProductInfo;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index 52a6380..98209bb 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
#undef LOG_TAG
#define LOG_TAG "DisplayIdentification"
@@ -38,7 +34,6 @@
constexpr size_t kEdidBlockSize = 128;
constexpr size_t kEdidHeaderLength = 5;
-constexpr uint16_t kFallbackEdidManufacturerId = 0;
constexpr uint16_t kVirtualEdidManufacturerId = 0xffffu;
std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) {
@@ -126,8 +121,8 @@
constexpr uint8_t kVendorSpecificDataBlockTag = 0x3;
if (tag == kVendorSpecificDataBlockTag) {
- const uint32_t ieeeRegistrationId =
- dataBlock[1] | (dataBlock[2] << 8) | (dataBlock[3] << 16);
+ const uint32_t ieeeRegistrationId = static_cast<uint32_t>(
+ dataBlock[1] | (dataBlock[2] << 8) | (dataBlock[3] << 16));
constexpr uint32_t kHdmiIeeeRegistrationId = 0xc03;
if (ieeeRegistrationId == kHdmiIeeeRegistrationId) {
@@ -152,14 +147,6 @@
} // namespace
-uint16_t DisplayId::manufacturerId() const {
- return static_cast<uint16_t>(value >> 40);
-}
-
-DisplayId DisplayId::fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t modelHash) {
- return {(static_cast<Type>(manufacturerId) << 40) | (static_cast<Type>(modelHash) << 8) | port};
-}
-
bool isEdid(const DisplayIdentificationData& data) {
const uint8_t kMagic[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0};
return data.size() >= sizeof(kMagic) &&
@@ -184,7 +171,7 @@
// Plug and play ID encoded as big-endian 16-bit value.
const uint16_t manufacturerId =
- (edid[kManufacturerOffset] << 8) | edid[kManufacturerOffset + 1];
+ static_cast<uint16_t>((edid[kManufacturerOffset] << 8) | edid[kManufacturerOffset + 1]);
const auto pnpId = getPnpId(manufacturerId);
if (!pnpId) {
@@ -197,7 +184,8 @@
ALOGE("Invalid EDID: product ID is truncated.");
return {};
}
- const uint16_t productId = edid[kProductIdOffset] | (edid[kProductIdOffset + 1] << 8);
+ const uint16_t productId =
+ static_cast<uint16_t>(edid[kProductIdOffset] | (edid[kProductIdOffset + 1] << 8));
constexpr size_t kManufactureWeekOffset = 16;
if (edid.size() < kManufactureWeekOffset + sizeof(uint8_t)) {
@@ -323,8 +311,8 @@
return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt;
}
-std::optional<PnpId> getPnpId(DisplayId displayId) {
- return getPnpId(displayId.manufacturerId());
+std::optional<PnpId> getPnpId(PhysicalDisplayId displayId) {
+ return getPnpId(displayId.getManufacturerId());
}
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
@@ -339,21 +327,15 @@
return {};
}
- const auto displayId = DisplayId::fromEdid(port, edid->manufacturerId, edid->modelHash);
+ const auto displayId = PhysicalDisplayId::fromEdid(port, edid->manufacturerId, edid->modelHash);
return DisplayIdentificationInfo{.id = displayId,
.name = std::string(edid->displayName),
.deviceProductInfo = buildDeviceProductInfo(*edid)};
}
-DisplayId getFallbackDisplayId(uint8_t port) {
- return DisplayId::fromEdid(port, kFallbackEdidManufacturerId, 0);
-}
-
-DisplayId getVirtualDisplayId(uint32_t id) {
- return DisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
+PhysicalDisplayId getVirtualDisplayId(uint32_t id) {
+ return PhysicalDisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
}
} // namespace android
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index 4819d1d..fbea4e5 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 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.
@@ -24,38 +24,18 @@
#include <vector>
#include <ui/DeviceProductInfo.h>
-#include <ui/PhysicalDisplayId.h>
+#include <ui/DisplayId.h>
#define LEGACY_DISPLAY_TYPE_PRIMARY 0
#define LEGACY_DISPLAY_TYPE_EXTERNAL 1
namespace android {
-struct DisplayId {
- using Type = PhysicalDisplayId;
- Type value;
-
- uint16_t manufacturerId() const;
-
- static DisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t modelHash);
-};
-
-inline bool operator==(DisplayId lhs, DisplayId rhs) {
- return lhs.value == rhs.value;
-}
-
-inline bool operator!=(DisplayId lhs, DisplayId rhs) {
- return !(lhs == rhs);
-}
-
-inline std::string to_string(DisplayId displayId) {
- return std::to_string(displayId.value);
-}
using DisplayIdentificationData = std::vector<uint8_t>;
struct DisplayIdentificationInfo {
- DisplayId id;
+ PhysicalDisplayId id;
std::string name;
std::optional<DeviceProductInfo> deviceProductInfo;
};
@@ -94,23 +74,12 @@
bool isEdid(const DisplayIdentificationData&);
std::optional<Edid> parseEdid(const DisplayIdentificationData&);
std::optional<PnpId> getPnpId(uint16_t manufacturerId);
-std::optional<PnpId> getPnpId(DisplayId);
+std::optional<PnpId> getPnpId(PhysicalDisplayId);
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
uint8_t port, const DisplayIdentificationData&);
-DisplayId getFallbackDisplayId(uint8_t port);
-DisplayId getVirtualDisplayId(uint32_t id);
+PhysicalDisplayId getVirtualDisplayId(uint32_t id);
} // namespace android
-namespace std {
-
-template <>
-struct hash<android::DisplayId> {
- size_t operator()(android::DisplayId displayId) const {
- return hash<android::DisplayId::Type>()(displayId.value);
- }
-};
-
-} // namespace std
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 6819ff4..12f26f6 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_SF_HWC2_H
-#define ANDROID_SF_HWC2_H
+#pragma once
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
@@ -36,15 +35,16 @@
#include "Hal.h"
namespace android {
- struct DisplayedFrameStats;
- class Fence;
- class FloatRect;
- class GraphicBuffer;
- namespace Hwc2 {
- class Composer;
- }
- class TestableSurfaceFlinger;
+class Fence;
+class FloatRect;
+class GraphicBuffer;
+class TestableSurfaceFlinger;
+struct DisplayedFrameStats;
+
+namespace Hwc2 {
+class Composer;
+} // namespace Hwc2
namespace HWC2 {
@@ -61,19 +61,17 @@
// All calls receive a sequenceId, which will be the value that was supplied to
// HWC2::Device::registerCallback(). It's used to help differentiate callbacks
// from different hardware composer instances.
-class ComposerCallback {
- public:
- virtual void onHotplugReceived(int32_t sequenceId, hal::HWDisplayId display,
- hal::Connection connection) = 0;
- virtual void onRefreshReceived(int32_t sequenceId, hal::HWDisplayId display) = 0;
- virtual void onVsyncReceived(int32_t sequenceId, hal::HWDisplayId display, int64_t timestamp,
- std::optional<hal::VsyncPeriodNanos> vsyncPeriod) = 0;
- virtual void onVsyncPeriodTimingChangedReceived(
- int32_t sequenceId, hal::HWDisplayId display,
- const hal::VsyncPeriodChangeTimeline& updatedTimeline) = 0;
- virtual void onSeamlessPossible(int32_t sequenceId, hal::HWDisplayId display) = 0;
+struct ComposerCallback {
+ virtual void onHotplugReceived(int32_t sequenceId, hal::HWDisplayId, hal::Connection) = 0;
+ virtual void onRefreshReceived(int32_t sequenceId, hal::HWDisplayId) = 0;
+ virtual void onVsyncReceived(int32_t sequenceId, hal::HWDisplayId, int64_t timestamp,
+ std::optional<hal::VsyncPeriodNanos>) = 0;
+ virtual void onVsyncPeriodTimingChangedReceived(int32_t sequenceId, hal::HWDisplayId,
+ const hal::VsyncPeriodChangeTimeline&) = 0;
+ virtual void onSeamlessPossible(int32_t sequenceId, hal::HWDisplayId) = 0;
- virtual ~ComposerCallback() = default;
+protected:
+ ~ComposerCallback() = default;
};
// Convenience C++ class to access per display functions directly.
@@ -454,5 +452,3 @@
} // namespace impl
} // namespace HWC2
} // namespace android
-
-#endif // ANDROID_SF_HWC2_H
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7a2f0f3..05ef599 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -284,7 +284,8 @@
return displayId;
}
-void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) {
+void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,
+ PhysicalDisplayId displayId) {
if (!mInternalHwcDisplayId) {
mInternalHwcDisplayId = hwcDisplayId;
} else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
@@ -865,7 +866,8 @@
result.append(mComposer->dumpDebugInfo());
}
-std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const {
+std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId(
+ hal::HWDisplayId hwcDisplayId) const {
if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
it != mPhysicalDisplayIdMap.end()) {
return it->second;
@@ -873,7 +875,8 @@
return {};
}
-std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
+std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(
+ PhysicalDisplayId displayId) const {
if (const auto it = mDisplayData.find(displayId);
it != mDisplayData.end() && !it->second.isVirtual) {
return it->second.hwcDisplay->getId();
@@ -937,7 +940,7 @@
port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
}
- return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
+ return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
.name = isPrimary ? "Internal display"
: "External display",
.deviceProductInfo = std::nullopt};
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b800038..698e3af 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -84,23 +84,22 @@
virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
- virtual bool getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
+ virtual bool getDisplayIdentificationData(hal::HWDisplayId, uint8_t* outPort,
DisplayIdentificationData* outData) const = 0;
- virtual bool hasCapability(hal::Capability capability) const = 0;
- virtual bool hasDisplayCapability(DisplayId displayId,
- hal::DisplayCapability capability) const = 0;
+ virtual bool hasCapability(hal::Capability) const = 0;
+ virtual bool hasDisplayCapability(DisplayId, hal::DisplayCapability) const = 0;
// Attempts to allocate a virtual display and returns its ID if created on the HWC device.
virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
- ui::PixelFormat* format) = 0;
+ ui::PixelFormat*) = 0;
- virtual void allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) = 0;
+ virtual void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId) = 0;
// Attempts to create a new layer on this display
- virtual HWC2::Layer* createLayer(DisplayId displayId) = 0;
+ virtual HWC2::Layer* createLayer(DisplayId) = 0;
// Destroy a previously created layer
- virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
+ virtual void destroyLayer(DisplayId, HWC2::Layer*) = 0;
// Gets any required composition change requests from the HWC device.
//
@@ -113,104 +112,97 @@
DisplayId, bool frameUsesClientComposition,
std::optional<DeviceRequestedChanges>* outChanges) = 0;
- virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
- const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
- ui::Dataspace dataspace) = 0;
+ virtual status_t setClientTarget(DisplayId, uint32_t slot, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& target, ui::Dataspace) = 0;
// Present layers to the display and read releaseFences.
- virtual status_t presentAndGetReleaseFences(DisplayId displayId) = 0;
+ virtual status_t presentAndGetReleaseFences(DisplayId) = 0;
// set power mode
- virtual status_t setPowerMode(DisplayId displayId, hal::PowerMode mode) = 0;
+ virtual status_t setPowerMode(DisplayId, hal::PowerMode) = 0;
// Sets a color transform to be applied to the result of composition
- virtual status_t setColorTransform(DisplayId displayId, const mat4& transform) = 0;
+ virtual status_t setColorTransform(DisplayId, const mat4& transform) = 0;
// reset state when an external, non-virtual display is disconnected
- virtual void disconnectDisplay(DisplayId displayId) = 0;
+ virtual void disconnectDisplay(DisplayId) = 0;
// get the present fence received from the last call to present.
- virtual sp<Fence> getPresentFence(DisplayId displayId) const = 0;
+ virtual sp<Fence> getPresentFence(DisplayId) const = 0;
// Get last release fence for the given layer
- virtual sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const = 0;
+ virtual sp<Fence> getLayerReleaseFence(DisplayId, HWC2::Layer*) const = 0;
// Set the output buffer and acquire fence for a virtual display.
// Returns INVALID_OPERATION if displayId is not a virtual display.
- virtual status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+ virtual status_t setOutputBuffer(DisplayId, const sp<Fence>& acquireFence,
const sp<GraphicBuffer>& buffer) = 0;
// After SurfaceFlinger has retrieved the release fences for all the frames,
// it can call this to clear the shared pointers in the release fence map
- virtual void clearReleaseFences(DisplayId displayId) = 0;
+ virtual void clearReleaseFences(DisplayId) = 0;
// Fetches the HDR capabilities of the given display
- virtual status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) = 0;
+ virtual status_t getHdrCapabilities(DisplayId, HdrCapabilities* outCapabilities) = 0;
- virtual int32_t getSupportedPerFrameMetadata(DisplayId displayId) const = 0;
+ virtual int32_t getSupportedPerFrameMetadata(DisplayId) const = 0;
// Returns the available RenderIntent of the given display.
- virtual std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
- ui::ColorMode colorMode) const = 0;
+ virtual std::vector<ui::RenderIntent> getRenderIntents(DisplayId, ui::ColorMode) const = 0;
- virtual mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) = 0;
+ virtual mat4 getDataspaceSaturationMatrix(DisplayId, ui::Dataspace) = 0;
// Returns the attributes of the color sampling engine.
- virtual status_t getDisplayedContentSamplingAttributes(DisplayId displayId,
- ui::PixelFormat* outFormat,
+ virtual status_t getDisplayedContentSamplingAttributes(DisplayId, ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) = 0;
- virtual status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
+ virtual status_t setDisplayContentSamplingEnabled(DisplayId, bool enabled,
uint8_t componentMask,
uint64_t maxFrames) = 0;
- virtual status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
- uint64_t timestamp,
+ virtual status_t getDisplayedContentSample(DisplayId, uint64_t maxFrames, uint64_t timestamp,
DisplayedFrameStats* outStats) = 0;
// Sets the brightness of a display.
- virtual std::future<status_t> setDisplayBrightness(DisplayId displayId, float brightness) = 0;
+ virtual std::future<status_t> setDisplayBrightness(DisplayId, float brightness) = 0;
// Events handling ---------------------------------------------------------
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
// This function is called from SurfaceFlinger.
- virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId hwcDisplayId,
- hal::Connection connection) = 0;
+ virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId,
+ hal::Connection) = 0;
- virtual bool onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) = 0;
- virtual void setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) = 0;
+ virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
+ virtual void setVsyncEnabled(DisplayId, hal::Vsync enabled) = 0;
- virtual nsecs_t getRefreshTimestamp(DisplayId displayId) const = 0;
- virtual bool isConnected(DisplayId displayId) const = 0;
+ virtual nsecs_t getRefreshTimestamp(DisplayId) const = 0;
+ virtual bool isConnected(DisplayId) const = 0;
// Non-const because it can update configMap inside of mDisplayData
virtual std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(
- DisplayId displayId) const = 0;
+ DisplayId) const = 0;
- virtual std::shared_ptr<const HWC2::Display::Config> getActiveConfig(
- DisplayId displayId) const = 0;
- virtual int getActiveConfigIndex(DisplayId displayId) const = 0;
+ virtual std::shared_ptr<const HWC2::Display::Config> getActiveConfig(DisplayId) const = 0;
+ virtual int getActiveConfigIndex(DisplayId) const = 0;
- virtual std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const = 0;
+ virtual std::vector<ui::ColorMode> getColorModes(DisplayId) const = 0;
- virtual status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
- ui::RenderIntent renderIntent) = 0;
+ virtual status_t setActiveColorMode(DisplayId, ui::ColorMode mode, ui::RenderIntent) = 0;
virtual bool isUsingVrComposer() const = 0;
// Composer 2.4
virtual DisplayConnectionType getDisplayConnectionType(DisplayId) const = 0;
- virtual bool isVsyncPeriodSwitchSupported(DisplayId displayId) const = 0;
- virtual nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const = 0;
+ virtual bool isVsyncPeriodSwitchSupported(DisplayId) const = 0;
+ virtual nsecs_t getDisplayVsyncPeriod(DisplayId) const = 0;
virtual status_t setActiveConfigWithConstraints(
- DisplayId displayId, size_t configId,
- const hal::VsyncPeriodChangeConstraints& constraints,
+ DisplayId, size_t configId, const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
- virtual status_t setAutoLowLatencyMode(DisplayId displayId, bool on) = 0;
+ virtual status_t setAutoLowLatencyMode(DisplayId, bool on) = 0;
virtual status_t getSupportedContentTypes(
- DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) = 0;
- virtual status_t setContentType(DisplayId displayId, hal::ContentType contentType) = 0;
+ DisplayId, std::vector<hal::ContentType>* outSupportedContentTypes) = 0;
+ virtual status_t setContentType(DisplayId, hal::ContentType) = 0;
virtual const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata()
const = 0;
@@ -223,8 +215,8 @@
virtual std::optional<hal::HWDisplayId> getInternalHwcDisplayId() const = 0;
virtual std::optional<hal::HWDisplayId> getExternalHwcDisplayId() const = 0;
- virtual std::optional<DisplayId> toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const = 0;
- virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(DisplayId displayId) const = 0;
+ virtual std::optional<PhysicalDisplayId> toPhysicalDisplayId(hal::HWDisplayId) const = 0;
+ virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(PhysicalDisplayId) const = 0;
};
namespace impl {
@@ -238,118 +230,112 @@
void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) override;
- bool getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
+ bool getDisplayIdentificationData(hal::HWDisplayId, uint8_t* outPort,
DisplayIdentificationData* outData) const override;
- bool hasCapability(hal::Capability capability) const override;
- bool hasDisplayCapability(DisplayId displayId,
- hal::DisplayCapability capability) const override;
+ bool hasCapability(hal::Capability) const override;
+ bool hasDisplayCapability(DisplayId, hal::DisplayCapability) const override;
// Attempts to allocate a virtual display and returns its ID if created on the HWC device.
std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
- ui::PixelFormat* format) override;
+ ui::PixelFormat*) override;
// Called from SurfaceFlinger, when the state for a new physical display needs to be recreated.
- void allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) override;
+ void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId) override;
// Attempts to create a new layer on this display
- HWC2::Layer* createLayer(DisplayId displayId) override;
+ HWC2::Layer* createLayer(DisplayId) override;
// Destroy a previously created layer
- void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
+ void destroyLayer(DisplayId, HWC2::Layer*) override;
status_t getDeviceCompositionChanges(
DisplayId, bool frameUsesClientComposition,
std::optional<DeviceRequestedChanges>* outChanges) override;
- status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
+ status_t setClientTarget(DisplayId, uint32_t slot, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& target, ui::Dataspace) override;
// Present layers to the display and read releaseFences.
- status_t presentAndGetReleaseFences(DisplayId displayId) override;
+ status_t presentAndGetReleaseFences(DisplayId) override;
// set power mode
- status_t setPowerMode(DisplayId displayId, hal::PowerMode mode) override;
+ status_t setPowerMode(DisplayId, hal::PowerMode mode) override;
// Sets a color transform to be applied to the result of composition
- status_t setColorTransform(DisplayId displayId, const mat4& transform) override;
+ status_t setColorTransform(DisplayId, const mat4& transform) override;
// reset state when an external, non-virtual display is disconnected
- void disconnectDisplay(DisplayId displayId) override;
+ void disconnectDisplay(DisplayId) override;
// get the present fence received from the last call to present.
- sp<Fence> getPresentFence(DisplayId displayId) const override;
+ sp<Fence> getPresentFence(DisplayId) const override;
// Get last release fence for the given layer
- sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const override;
+ sp<Fence> getLayerReleaseFence(DisplayId, HWC2::Layer*) const override;
// Set the output buffer and acquire fence for a virtual display.
// Returns INVALID_OPERATION if displayId is not a virtual display.
- status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+ status_t setOutputBuffer(DisplayId, const sp<Fence>& acquireFence,
const sp<GraphicBuffer>& buffer) override;
// After SurfaceFlinger has retrieved the release fences for all the frames,
// it can call this to clear the shared pointers in the release fence map
- void clearReleaseFences(DisplayId displayId) override;
+ void clearReleaseFences(DisplayId) override;
// Fetches the HDR capabilities of the given display
- status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) override;
+ status_t getHdrCapabilities(DisplayId, HdrCapabilities* outCapabilities) override;
- int32_t getSupportedPerFrameMetadata(DisplayId displayId) const override;
+ int32_t getSupportedPerFrameMetadata(DisplayId) const override;
// Returns the available RenderIntent of the given display.
- std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
- ui::ColorMode colorMode) const override;
+ std::vector<ui::RenderIntent> getRenderIntents(DisplayId, ui::ColorMode) const override;
- mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) override;
+ mat4 getDataspaceSaturationMatrix(DisplayId, ui::Dataspace) override;
// Returns the attributes of the color sampling engine.
- status_t getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat,
+ status_t getDisplayedContentSamplingAttributes(DisplayId, ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) override;
- status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
- uint8_t componentMask, uint64_t maxFrames) override;
- status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp,
+ status_t setDisplayContentSamplingEnabled(DisplayId, bool enabled, uint8_t componentMask,
+ uint64_t maxFrames) override;
+ status_t getDisplayedContentSample(DisplayId, uint64_t maxFrames, uint64_t timestamp,
DisplayedFrameStats* outStats) override;
- std::future<status_t> setDisplayBrightness(DisplayId displayId, float brightness) override;
+ std::future<status_t> setDisplayBrightness(DisplayId, float brightness) override;
// Events handling ---------------------------------------------------------
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
- std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId hwcDisplayId,
- hal::Connection connection) override;
+ std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, hal::Connection) override;
- bool onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) override;
- void setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) override;
+ bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
+ void setVsyncEnabled(DisplayId, hal::Vsync enabled) override;
- nsecs_t getRefreshTimestamp(DisplayId displayId) const override;
- bool isConnected(DisplayId displayId) const override;
+ nsecs_t getRefreshTimestamp(DisplayId) const override;
+ bool isConnected(DisplayId) const override;
// Non-const because it can update configMap inside of mDisplayData
- std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(
- DisplayId displayId) const override;
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(DisplayId) const override;
- std::shared_ptr<const HWC2::Display::Config> getActiveConfig(
- DisplayId displayId) const override;
- int getActiveConfigIndex(DisplayId displayId) const override;
+ std::shared_ptr<const HWC2::Display::Config> getActiveConfig(DisplayId) const override;
+ int getActiveConfigIndex(DisplayId) const override;
- std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const override;
+ std::vector<ui::ColorMode> getColorModes(DisplayId) const override;
- status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
- ui::RenderIntent renderIntent) override;
+ status_t setActiveColorMode(DisplayId, ui::ColorMode, ui::RenderIntent) override;
bool isUsingVrComposer() const override;
// Composer 2.4
DisplayConnectionType getDisplayConnectionType(DisplayId) const override;
- bool isVsyncPeriodSwitchSupported(DisplayId displayId) const override;
- nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const override;
- status_t setActiveConfigWithConstraints(DisplayId displayId, size_t configId,
- const hal::VsyncPeriodChangeConstraints& constraints,
+ bool isVsyncPeriodSwitchSupported(DisplayId) const override;
+ nsecs_t getDisplayVsyncPeriod(DisplayId) const override;
+ status_t setActiveConfigWithConstraints(DisplayId, size_t configId,
+ const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
- status_t setAutoLowLatencyMode(DisplayId displayId, bool) override;
- status_t getSupportedContentTypes(DisplayId displayId, std::vector<hal::ContentType>*) override;
- status_t setContentType(DisplayId displayId, hal::ContentType) override;
+ status_t setAutoLowLatencyMode(DisplayId, bool) override;
+ status_t getSupportedContentTypes(DisplayId, std::vector<hal::ContentType>*) override;
+ status_t setContentType(DisplayId, hal::ContentType) override;
const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata() const override;
@@ -366,17 +352,16 @@
return mExternalHwcDisplayId;
}
- std::optional<DisplayId> toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const override;
- std::optional<hal::HWDisplayId> fromPhysicalDisplayId(DisplayId displayId) const override;
+ std::optional<PhysicalDisplayId> toPhysicalDisplayId(hal::HWDisplayId) const override;
+ std::optional<hal::HWDisplayId> fromPhysicalDisplayId(PhysicalDisplayId) const override;
private:
// For unit tests
friend TestableSurfaceFlinger;
- std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId hwcDisplayId);
- std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hal::HWDisplayId hwcDisplayId);
- bool shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
- bool hasDisplayIdentificationData) const;
+ std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
+ std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hal::HWDisplayId);
+ bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
void loadCapabilities();
void loadLayerMetadataSupport();
@@ -411,7 +396,7 @@
std::unordered_map<std::string, bool> mSupportedLayerGenericMetadata;
bool mRegisteredCallback = false;
- std::unordered_map<hal::HWDisplayId, DisplayId> mPhysicalDisplayIdMap;
+ std::unordered_map<hal::HWDisplayId, PhysicalDisplayId> mPhysicalDisplayIdMap;
std::optional<hal::HWDisplayId> mInternalHwcDisplayId;
std::optional<hal::HWDisplayId> mExternalHwcDisplayId;
bool mHasMultiDisplaySupport = false;
diff --git a/services/surfaceflinger/DisplayRenderArea.cpp b/services/surfaceflinger/DisplayRenderArea.cpp
index 7cd283d..bcebf23 100644
--- a/services/surfaceflinger/DisplayRenderArea.cpp
+++ b/services/surfaceflinger/DisplayRenderArea.cpp
@@ -129,7 +129,7 @@
Rect DisplayRenderArea::getSourceCrop() const {
// use the projected display viewport by default.
if (mSourceCrop.isEmpty()) {
- return mDisplay->getSourceClip();
+ return mDisplay->getViewport();
}
// If there is a source crop provided then it is assumed that the device
@@ -144,8 +144,8 @@
}
const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
- int width = mDisplay->getSourceClip().getWidth();
- int height = mDisplay->getSourceClip().getHeight();
+ int width = mDisplay->getViewport().getWidth();
+ int height = mDisplay->getViewport().getHeight();
ui::Transform rotation;
rotation.set(flags, width, height);
return rotation.transform(mSourceCrop);
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 899d1fa..17daadb 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -442,9 +442,10 @@
PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
}
- bool ignored;
+ ScreenCaptureResults captureResults;
mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- false /* identityTransform */, true /* regionSampling */, ignored);
+ false /* identityTransform */, true /* regionSampling */,
+ captureResults);
std::vector<Descriptor> activeDescriptors;
for (const auto& descriptor : descriptors) {
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index ff91bf7..46112f5 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -340,7 +340,7 @@
return nextEventTime;
}
- // Sanity check that the duration is close enough in length to a period without
+ // Check that the duration is close enough in length to a period without
// falling into double-rate vsyncs.
bool isCloseToPeriod(nsecs_t duration) {
// Ratio of 3/5 is arbitrary, but it must be greater than 1/2.
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index 832f08e..6fb5654 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -227,7 +227,7 @@
// mZeroErrSamplesCount keeps track of how many times in a row there were
// zero timestamps available in the mPresentFences array.
- // Used to sanity check that we are able to calculate the model error.
+ // Used to check that we are able to calculate the model error.
size_t mZeroErrSamplesCount;
// Whether we have updated the vsync event model since the last resync.
diff --git a/services/surfaceflinger/Scheduler/EventControlThread.cpp b/services/surfaceflinger/Scheduler/EventControlThread.cpp
deleted file mode 100644
index 7f9db9c..0000000
--- a/services/surfaceflinger/Scheduler/EventControlThread.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include <pthread.h>
-#include <sched.h>
-#include <sys/resource.h>
-
-#include <cutils/sched_policy.h>
-#include <log/log.h>
-#include <system/thread_defs.h>
-
-#include "EventControlThread.h"
-
-namespace android {
-
-EventControlThread::~EventControlThread() = default;
-
-namespace impl {
-
-EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function)
- : mSetVSyncEnabled(std::move(function)) {
- pthread_setname_np(mThread.native_handle(), "EventControlThread");
-
- pid_t tid = pthread_gettid_np(mThread.native_handle());
- setpriority(PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY);
- set_sched_policy(tid, SP_FOREGROUND);
-}
-
-EventControlThread::~EventControlThread() {
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mKeepRunning = false;
- mCondition.notify_all();
- }
- mThread.join();
-}
-
-void EventControlThread::setVsyncEnabled(bool enabled) {
- std::lock_guard<std::mutex> lock(mMutex);
- mVsyncEnabled = enabled;
- mCondition.notify_all();
-}
-
-// Unfortunately std::unique_lock gives warnings with -Wthread-safety
-void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
- auto keepRunning = true;
- auto currentVsyncEnabled = false;
-
- while (keepRunning) {
- mSetVSyncEnabled(currentVsyncEnabled);
-
- std::unique_lock<std::mutex> lock(mMutex);
- mCondition.wait(lock, [this, currentVsyncEnabled, keepRunning]() NO_THREAD_SAFETY_ANALYSIS {
- return currentVsyncEnabled != mVsyncEnabled || keepRunning != mKeepRunning;
- });
- currentVsyncEnabled = mVsyncEnabled;
- keepRunning = mKeepRunning;
- }
-}
-
-} // namespace impl
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/Scheduler/EventControlThread.h b/services/surfaceflinger/Scheduler/EventControlThread.h
deleted file mode 100644
index cafae53..0000000
--- a/services/surfaceflinger/Scheduler/EventControlThread.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <condition_variable>
-#include <cstddef>
-#include <functional>
-#include <mutex>
-#include <thread>
-
-#include <android-base/thread_annotations.h>
-
-namespace android {
-
-class EventControlThread {
-public:
- virtual ~EventControlThread();
-
- virtual void setVsyncEnabled(bool enabled) = 0;
-};
-
-namespace impl {
-
-class EventControlThread final : public android::EventControlThread {
-public:
- using SetVSyncEnabledFunction = std::function<void(bool)>;
-
- explicit EventControlThread(SetVSyncEnabledFunction function);
- ~EventControlThread();
-
- // EventControlThread implementation
- void setVsyncEnabled(bool enabled) override;
-
-private:
- void threadMain();
-
- std::mutex mMutex;
- std::condition_variable mCondition;
-
- const SetVSyncEnabledFunction mSetVSyncEnabled;
- bool mVsyncEnabled GUARDED_BY(mMutex) = false;
- bool mKeepRunning GUARDED_BY(mMutex) = true;
-
- // Must be last so that everything is initialized before the thread starts.
- std::thread mThread{&EventControlThread::threadMain, this};
-};
-
-} // namespace impl
-} // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index cee36a1..2020e0c 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -74,18 +74,16 @@
std::string toString(const DisplayEventReceiver::Event& event) {
switch (event.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
- return StringPrintf("Hotplug{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", %s}",
- event.header.displayId,
+ return StringPrintf("Hotplug{displayId=%s, %s}",
+ to_string(event.header.displayId).c_str(),
event.hotplug.connected ? "connected" : "disconnected");
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
- return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
- ", count=%u, expectedVSyncTimestamp=%" PRId64 "}",
- event.header.displayId, event.vsync.count,
+ return StringPrintf("VSync{displayId=%s, count=%u, expectedVSyncTimestamp=%" PRId64 "}",
+ to_string(event.header.displayId).c_str(), event.vsync.count,
event.vsync.expectedVSyncTimestamp);
case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
- return StringPrintf("ConfigChanged{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
- ", configId=%u}",
- event.header.displayId, event.config.configId);
+ return StringPrintf("ConfigChanged{displayId=%s, configId=%u}",
+ to_string(event.header.displayId).c_str(), event.config.configId);
default:
return "Event{}";
}
@@ -508,8 +506,8 @@
StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState));
if (mVSyncState) {
- StringAppendF(&result, "{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%u%s}\n",
- mVSyncState->displayId, mVSyncState->count,
+ StringAppendF(&result, "{displayId=%s, count=%u%s}\n",
+ to_string(mVSyncState->displayId).c_str(), mVSyncState->count,
mVSyncState->synthetic ? ", synthetic" : "");
} else {
StringAppendF(&result, "none\n");
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b53e2dc..4f4c1d0 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -20,11 +20,11 @@
#include "Scheduler.h"
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
-#include <cutils/properties.h>
#include <input/InputWindow.h>
#include <system/window.h>
#include <ui/DisplayStatInfo.h>
@@ -41,7 +41,6 @@
#include "../Layer.h"
#include "DispSync.h"
#include "DispSyncSource.h"
-#include "EventControlThread.h"
#include "EventThread.h"
#include "InjectVSyncSource.h"
#include "OneShotTimer.h"
@@ -60,54 +59,35 @@
} \
} while (false)
+using namespace std::string_literals;
+
namespace android {
namespace {
std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() {
- // TODO (144707443) tune Predictor tunables.
- static constexpr int default_rate = 60;
- static constexpr auto initial_period =
- std::chrono::duration<nsecs_t, std::ratio<1, default_rate>>(1);
- static constexpr size_t vsyncTimestampHistorySize = 20;
- static constexpr size_t minimumSamplesForPrediction = 6;
- static constexpr uint32_t discardOutlierPercent = 20;
- return std::make_unique<
- scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
- initial_period)
- .count(),
- vsyncTimestampHistorySize, minimumSamplesForPrediction,
- discardOutlierPercent);
+ // TODO(b/144707443): Tune constants.
+ constexpr int kDefaultRate = 60;
+ constexpr auto initialPeriod = std::chrono::duration<nsecs_t, std::ratio<1, kDefaultRate>>(1);
+ constexpr nsecs_t idealPeriod =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(initialPeriod).count();
+ constexpr size_t vsyncTimestampHistorySize = 20;
+ constexpr size_t minimumSamplesForPrediction = 6;
+ constexpr uint32_t discardOutlierPercent = 20;
+ return std::make_unique<scheduler::VSyncPredictor>(idealPeriod, vsyncTimestampHistorySize,
+ minimumSamplesForPrediction,
+ discardOutlierPercent);
}
-std::unique_ptr<scheduler::VSyncDispatch> createVSyncDispatch(
- const std::unique_ptr<scheduler::VSyncTracker>& vSyncTracker) {
- if (!vSyncTracker) return {};
-
- // TODO (144707443) tune Predictor tunables.
- static constexpr auto vsyncMoveThreshold =
- std::chrono::duration_cast<std::chrono::nanoseconds>(3ms);
- static constexpr auto timerSlack = std::chrono::duration_cast<std::chrono::nanoseconds>(500us);
+std::unique_ptr<scheduler::VSyncDispatch> createVSyncDispatch(scheduler::VSyncTracker& tracker) {
+ // TODO(b/144707443): Tune constants.
+ constexpr std::chrono::nanoseconds vsyncMoveThreshold = 3ms;
+ constexpr std::chrono::nanoseconds timerSlack = 500us;
return std::make_unique<
- scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), *vSyncTracker,
+ scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), tracker,
timerSlack.count(), vsyncMoveThreshold.count());
}
-std::unique_ptr<DispSync> createDispSync(
- const std::unique_ptr<scheduler::VSyncTracker>& vSyncTracker,
- const std::unique_ptr<scheduler::VSyncDispatch>& vSyncDispatch, bool supportKernelTimer) {
- if (vSyncTracker && vSyncDispatch) {
- // TODO (144707443) tune Predictor tunables.
- static constexpr size_t pendingFenceLimit = 20;
- return std::make_unique<scheduler::VSyncReactor>(std::make_unique<scheduler::SystemClock>(),
- *vSyncDispatch, *vSyncTracker,
- pendingFenceLimit, supportKernelTimer);
- } else {
- return std::make_unique<impl::DispSync>("SchedulerDispSync",
- sysprop::running_without_sync_framework(true));
- }
-}
-
const char* toContentDetectionString(bool useContentDetection, bool useContentDetectionV2) {
if (!useContentDetection) return "off";
return useContentDetectionV2 ? "V2" : "V1";
@@ -115,29 +95,26 @@
} // namespace
-Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
- const scheduler::RefreshRateConfigs& refreshRateConfigs,
- ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
- bool useContentDetection)
- : mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
- // TODO (140302863) remove this and use the vsync_reactor system.
- mUseVsyncPredictor(property_get_bool("debug.sf.vsync_reactor", true)),
- mVSyncTracker(mUseVsyncPredictor ? createVSyncTracker() : nullptr),
- mVSyncDispatch(createVSyncDispatch(mVSyncTracker)),
- mPrimaryDispSync(createDispSync(mVSyncTracker, mVSyncDispatch, mSupportKernelTimer)),
- mEventControlThread(new impl::EventControlThread(std::move(function))),
- mLayerHistory(createLayerHistory(refreshRateConfigs, useContentDetectionV2)),
- mSchedulerCallback(schedulerCallback),
- mRefreshRateConfigs(refreshRateConfigs),
- mUseContentDetection(useContentDetection),
- mUseContentDetectionV2(useContentDetectionV2) {
+Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
+ : Scheduler(configs, callback,
+ {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
+ .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false),
+ .useContentDetectionV2 =
+ base::GetBoolProperty("debug.sf.use_content_detection_v2"s, true),
+ // TODO(b/140302863): Remove this and use the vsync_reactor system.
+ .useVsyncPredictor = base::GetBoolProperty("debug.sf.vsync_reactor"s, true)}) {}
+
+Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
+ Options options)
+ : Scheduler(createVsyncSchedule(options), configs, callback,
+ createLayerHistory(configs, options.useContentDetectionV2), options) {
using namespace sysprop;
- const int setIdleTimerMs = property_get_int32("debug.sf.set_idle_timer_ms", 0);
+ const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);
if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) {
- const auto callback = mSupportKernelTimer ? &Scheduler::kernelIdleTimerCallback
- : &Scheduler::idleTimerCallback;
+ const auto callback = mOptions.supportKernelTimer ? &Scheduler::kernelIdleTimerCallback
+ : &Scheduler::idleTimerCallback;
mIdleTimer.emplace(
std::chrono::milliseconds(millis),
[this, callback] { std::invoke(callback, this, TimerState::Reset); },
@@ -163,21 +140,16 @@
}
}
-Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
- std::unique_ptr<EventControlThread> eventControlThread,
- const scheduler::RefreshRateConfigs& configs,
+Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,
ISchedulerCallback& schedulerCallback,
- std::unique_ptr<LayerHistory> layerHistory, bool useContentDetectionV2,
- bool useContentDetection)
- : mSupportKernelTimer(false),
- mUseVsyncPredictor(true),
- mPrimaryDispSync(std::move(primaryDispSync)),
- mEventControlThread(std::move(eventControlThread)),
+ std::unique_ptr<LayerHistory> layerHistory, Options options)
+ : mOptions(options),
+ mVsyncSchedule(std::move(schedule)),
mLayerHistory(std::move(layerHistory)),
mSchedulerCallback(schedulerCallback),
- mRefreshRateConfigs(configs),
- mUseContentDetection(useContentDetection),
- mUseContentDetectionV2(useContentDetectionV2) {}
+ mRefreshRateConfigs(configs) {
+ mSchedulerCallback.setVsyncEnabled(false);
+}
Scheduler::~Scheduler() {
// Ensure the OneShotTimer threads are joined before we start destroying state.
@@ -186,6 +158,25 @@
mIdleTimer.reset();
}
+Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(Options options) {
+ if (!options.useVsyncPredictor) {
+ auto sync = std::make_unique<impl::DispSync>("SchedulerDispSync",
+ sysprop::running_without_sync_framework(true));
+ return {std::move(sync), nullptr, nullptr};
+ }
+
+ auto clock = std::make_unique<scheduler::SystemClock>();
+ auto tracker = createVSyncTracker();
+ auto dispatch = createVSyncDispatch(*tracker);
+
+ // TODO(b/144707443): Tune constants.
+ constexpr size_t pendingFenceLimit = 20;
+ auto sync = std::make_unique<scheduler::VSyncReactor>(std::move(clock), *dispatch, *tracker,
+ pendingFenceLimit,
+ options.supportKernelTimer);
+ return {std::move(sync), std::move(tracker), std::move(dispatch)};
+}
+
std::unique_ptr<LayerHistory> Scheduler::createLayerHistory(
const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) {
if (!configs.canSwitch()) return nullptr;
@@ -198,12 +189,12 @@
}
DispSync& Scheduler::getPrimaryDispSync() {
- return *mPrimaryDispSync;
+ return *mVsyncSchedule.sync;
}
std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(const char* name,
nsecs_t phaseOffsetNs) {
- return std::make_unique<DispSyncSource>(mPrimaryDispSync.get(), phaseOffsetNs,
+ return std::make_unique<DispSyncSource>(&getPrimaryDispSync(), phaseOffsetNs,
true /* traceVsync */, name);
}
@@ -309,8 +300,8 @@
}
void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
- stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0, systemTime());
- stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+ stats->vsyncTime = getPrimaryDispSync().computeNextRefresh(0, systemTime());
+ stats->vsyncPeriod = getPrimaryDispSync().getPeriod();
}
Scheduler::ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
@@ -347,8 +338,8 @@
void Scheduler::enableHardwareVsync() {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
- mPrimaryDispSync->beginResync();
- mEventControlThread->setVsyncEnabled(true);
+ getPrimaryDispSync().beginResync();
+ mSchedulerCallback.setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
}
@@ -356,8 +347,8 @@
void Scheduler::disableHardwareVsync(bool makeUnavailable) {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
- mEventControlThread->setVsyncEnabled(false);
- mPrimaryDispSync->endResync();
+ mSchedulerCallback.setVsyncEnabled(false);
+ getPrimaryDispSync().endResync();
mPrimaryHWVsyncEnabled = false;
}
if (makeUnavailable) {
@@ -397,11 +388,11 @@
void Scheduler::setVsyncPeriod(nsecs_t period) {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
- mPrimaryDispSync->setPeriod(period);
+ getPrimaryDispSync().setPeriod(period);
if (!mPrimaryHWVsyncEnabled) {
- mPrimaryDispSync->beginResync();
- mEventControlThread->setVsyncEnabled(true);
+ getPrimaryDispSync().beginResync();
+ mSchedulerCallback.setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
}
@@ -414,7 +405,7 @@
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
needsHwVsync =
- mPrimaryDispSync->addResyncSample(timestamp, hwcVsyncPeriod, periodFlushed);
+ getPrimaryDispSync().addResyncSample(timestamp, hwcVsyncPeriod, periodFlushed);
}
}
@@ -426,7 +417,7 @@
}
void Scheduler::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
- if (mPrimaryDispSync->addPresentFence(fenceTime)) {
+ if (getPrimaryDispSync().addPresentFence(fenceTime)) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
@@ -434,11 +425,11 @@
}
void Scheduler::setIgnorePresentFences(bool ignore) {
- mPrimaryDispSync->setIgnorePresentFences(ignore);
+ getPrimaryDispSync().setIgnorePresentFences(ignore);
}
nsecs_t Scheduler::getDispSyncExpectedPresentTime(nsecs_t now) {
- return mPrimaryDispSync->expectedPresentTime(now);
+ return getPrimaryDispSync().expectedPresentTime(now);
}
void Scheduler::registerLayer(Layer* layer) {
@@ -450,13 +441,13 @@
if (layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) {
mLayerHistory->registerLayer(layer, minFps, maxFps,
scheduler::LayerHistory::LayerVoteType::NoVote);
- } else if (!mUseContentDetection) {
+ } else if (!mOptions.useContentDetection) {
// If the content detection feature is off, all layers are registered at Max. We still keep
// the layer history, since we use it for other features (like Frame Rate API), so layers
// still need to be registered.
mLayerHistory->registerLayer(layer, minFps, maxFps,
scheduler::LayerHistory::LayerVoteType::Max);
- } else if (!mUseContentDetectionV2) {
+ } else if (!mOptions.useContentDetectionV2) {
// In V1 of content detection, all layers are registered as Heuristic (unless it's
// wallpaper).
const auto highFps =
@@ -533,7 +524,7 @@
if (mTouchTimer) {
mTouchTimer->reset();
- if (mSupportKernelTimer && mIdleTimer) {
+ if (mOptions.supportKernelTimer && mIdleTimer) {
mIdleTimer->reset();
}
}
@@ -610,7 +601,8 @@
StringAppendF(&result, "+ Touch timer: %s\n",
mTouchTimer ? mTouchTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Content detection: %s %s\n\n",
- toContentDetectionString(mUseContentDetection, mUseContentDetectionV2),
+ toContentDetectionString(mOptions.useContentDetection,
+ mOptions.useContentDetectionV2),
mLayerHistory ? mLayerHistory->dump().c_str() : "(no layer history)");
}
@@ -658,7 +650,7 @@
const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
- if (!mUseContentDetectionV2) {
+ if (!mOptions.useContentDetectionV2) {
// As long as touch is active we want to be in performance mode.
if (touchActive) {
return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 2fe5629..6a5082a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -29,7 +29,6 @@
#include <ui/GraphicTypes.h>
#pragma clang diagnostic pop
-#include "EventControlThread.h"
#include "EventThread.h"
#include "LayerHistory.h"
#include "OneShotTimer.h"
@@ -50,19 +49,22 @@
class VSyncTracker;
} // namespace scheduler
-class ISchedulerCallback {
-public:
- virtual ~ISchedulerCallback() = default;
+struct ISchedulerCallback {
+ virtual void setVsyncEnabled(bool) = 0;
virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
scheduler::RefreshRateConfigEvent) = 0;
virtual void repaintEverythingForHWC() = 0;
virtual void kernelTimerChanged(bool expired) = 0;
+
+protected:
+ ~ISchedulerCallback() = default;
};
-class IPhaseOffsetControl {
-public:
- virtual ~IPhaseOffsetControl() = default;
+struct IPhaseOffsetControl {
virtual void setPhaseOffset(scheduler::ConnectionHandle, nsecs_t phaseOffset) = 0;
+
+protected:
+ ~IPhaseOffsetControl() = default;
};
class Scheduler : public IPhaseOffsetControl {
@@ -78,10 +80,7 @@
Normal // Start the transaction at the normal time
};
- Scheduler(impl::EventControlThread::SetVSyncEnabledFunction,
- const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback,
- bool useContentDetectionV2, bool useContentDetection);
-
+ Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&);
virtual ~Scheduler();
DispSync& getPrimaryDispSync();
@@ -176,11 +175,31 @@
enum class TimerState { Reset, Expired };
enum class TouchState { Inactive, Active };
- // Used by tests to inject mocks.
- Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
- const scheduler::RefreshRateConfigs&, ISchedulerCallback&,
- std::unique_ptr<LayerHistory>, bool useContentDetectionV2, bool useContentDetection);
+ struct Options {
+ // Whether to use idle timer callbacks that support the kernel timer.
+ bool supportKernelTimer;
+ // Whether to use content detection at all.
+ bool useContentDetection;
+ // Whether to use improved content detection.
+ bool useContentDetectionV2;
+ // Whether to use improved DispSync implementation.
+ bool useVsyncPredictor;
+ };
+ struct VsyncSchedule {
+ std::unique_ptr<DispSync> sync;
+ std::unique_ptr<scheduler::VSyncTracker> tracker;
+ std::unique_ptr<scheduler::VSyncDispatch> dispatch;
+ };
+
+ // Unlike the testing constructor, this creates the VsyncSchedule, LayerHistory, and timers.
+ Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&, Options);
+
+ // Used by tests to inject mocks.
+ Scheduler(VsyncSchedule, const scheduler::RefreshRateConfigs&, ISchedulerCallback&,
+ std::unique_ptr<LayerHistory>, Options);
+
+ static VsyncSchedule createVsyncSchedule(Options);
static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&,
bool useContentDetectionV2);
@@ -231,14 +250,8 @@
std::atomic<nsecs_t> mLastResyncTime = 0;
- // Whether to use idle timer callbacks that support the kernel timer.
- const bool mSupportKernelTimer;
-
- const bool mUseVsyncPredictor;
- const std::unique_ptr<scheduler::VSyncTracker> mVSyncTracker;
- const std::unique_ptr<scheduler::VSyncDispatch> mVSyncDispatch;
- std::unique_ptr<DispSync> mPrimaryDispSync;
- std::unique_ptr<EventControlThread> mEventControlThread;
+ const Options mOptions;
+ VsyncSchedule mVsyncSchedule;
// Used to choose refresh rate if content detection is enabled.
const std::unique_ptr<LayerHistory> mLayerHistory;
@@ -284,11 +297,6 @@
std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
GUARDED_BY(mVsyncTimelineLock);
static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
-
- // This variable indicates whether to use the content detection feature at all.
- const bool mUseContentDetection;
- // This variable indicates whether to use V2 version of the content detection.
- const bool mUseContentDetectionV2;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3b562bf..4e0d375 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -119,7 +119,6 @@
#include "RegionSamplingThread.h"
#include "Scheduler/DispSync.h"
#include "Scheduler/DispSyncSource.h"
-#include "Scheduler/EventControlThread.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/MessageQueue.h"
@@ -565,11 +564,11 @@
std::vector<PhysicalDisplayId> displayIds;
displayIds.reserve(mPhysicalDisplayTokens.size());
- displayIds.push_back(internalDisplayId->value);
+ displayIds.push_back(*internalDisplayId);
for (const auto& [id, token] : mPhysicalDisplayTokens) {
if (id != *internalDisplayId) {
- displayIds.push_back(id.value);
+ displayIds.push_back(id);
}
}
@@ -578,7 +577,7 @@
sp<IBinder> SurfaceFlinger::getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
Mutex::Autolock lock(mStateLock);
- return getPhysicalDisplayTokenLocked(DisplayId{displayId});
+ return getPhysicalDisplayTokenLocked(displayId);
}
status_t SurfaceFlinger::getColorManagement(bool* outGetColorManagement) const {
@@ -738,10 +737,11 @@
signalTransaction();
}));
};
- mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
- getHwComposer()
- .fromPhysicalDisplayId(*display->getId())
- .value_or(0),
+ auto hwcDisplayId =
+ getHwComposer()
+ .fromPhysicalDisplayId(static_cast<PhysicalDisplayId>(*display->getId()))
+ .value_or(0);
+ mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(), hwcDisplayId,
vrFlingerRequestDisplayCallback);
if (!mVrFlinger) {
ALOGE("Failed to start vrflinger");
@@ -1106,7 +1106,8 @@
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId)
.getVsyncPeriod();
- mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
+ mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle,
+ static_cast<PhysicalDisplayId>(*display->getId()),
mUpcomingActiveConfig.configId, vsyncPeriod);
}
}
@@ -1567,7 +1568,7 @@
mEventQueue->refresh();
}
-nsecs_t SurfaceFlinger::getVsyncPeriod() const {
+nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
const auto displayId = getInternalDisplayIdLocked();
if (!displayId || !getHwComposer().isConnected(*displayId)) {
return 0;
@@ -1679,25 +1680,18 @@
repaintEverythingForHWC();
}
-void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
+void SurfaceFlinger::setVsyncEnabled(bool enabled) {
ATRACE_CALL();
- // Enable / Disable HWVsync from the main thread to avoid race conditions with
- // display power state.
- static_cast<void>(schedule([=]() MAIN_THREAD { setPrimaryVsyncEnabledInternal(enabled); }));
-}
+ // On main thread to avoid race conditions with display power state.
+ static_cast<void>(schedule([=]() MAIN_THREAD {
+ mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
-void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
- ATRACE_CALL();
-
- mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
-
- if (const auto displayId = getInternalDisplayIdLocked()) {
- sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
- if (display && display->isPoweredOn()) {
- getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
+ if (const auto display = getDefaultDisplayDeviceLocked();
+ display && display->isPoweredOn()) {
+ getHwComposer().setVsyncEnabled(*display->getId(), mHWCVsyncPendingState);
}
- }
+ }));
}
void SurfaceFlinger::resetDisplayState() {
@@ -1774,7 +1768,7 @@
setPowerModeInternal(display, currentDisplayPowerMode);
// Reset the timing values to account for the period of the swapped in HWC
- const nsecs_t vsyncPeriod = getVsyncPeriod();
+ const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
// The present fences returned from vr_hwc are not an accurate
@@ -2440,7 +2434,7 @@
continue;
}
- const DisplayId displayId = info->id;
+ const auto displayId = info->id;
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
@@ -2654,7 +2648,7 @@
mDisplays.emplace(displayToken, display);
if (!state.isVirtual()) {
LOG_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, true);
+ dispatchDisplayHotplugEvent(static_cast<PhysicalDisplayId>(*displayId), true);
}
if (display->isPrimary()) {
@@ -2670,7 +2664,7 @@
if (!display->isVirtual()) {
LOG_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, false);
+ dispatchDisplayHotplugEvent(static_cast<PhysicalDisplayId>(*displayId), false);
}
}
@@ -2964,7 +2958,7 @@
changeRefreshRateLocked(refreshRate, event);
}
-void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
+void SurfaceFlinger::initScheduler(PhysicalDisplayId primaryDisplayId) {
if (mScheduler) {
// In practice it's not allowed to hotplug in/out the primary display once it's been
// connected during startup, but some tests do it, so just warn and return.
@@ -2985,9 +2979,7 @@
mPhaseConfiguration = getFactory().createPhaseConfiguration(*mRefreshRateConfigs);
// start the EventThread
- mScheduler =
- getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
- *mRefreshRateConfigs, *this);
+ mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseConfiguration->getCurrentOffsets().late.app,
impl::EventThread::InterceptVSyncsCallback());
@@ -3013,8 +3005,8 @@
// anyway since there are no connected apps at this point.
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod();
- mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, primaryDisplayId.value,
- currentConfig, vsyncPeriod);
+ mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, primaryDisplayId, currentConfig,
+ vsyncPeriod);
}
void SurfaceFlinger::commitTransaction()
@@ -4208,8 +4200,7 @@
{});
setPowerModeInternal(display, hal::PowerMode::ON);
-
- const nsecs_t vsyncPeriod = getVsyncPeriod();
+ const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
// Use phase of 0 since phase is not known.
@@ -4244,7 +4235,7 @@
if (mInterceptor->isEnabled()) {
mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
}
-
+ const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
if (currentMode == hal::PowerMode::OFF) {
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
@@ -4253,7 +4244,7 @@
if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
}
mVisibleRegionsDirty = true;
@@ -4280,7 +4271,7 @@
getHwComposer().setPowerMode(*displayId, mode);
if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
}
} else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
@@ -4393,7 +4384,7 @@
}
void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const {
- StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriod());
+ StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriodFromHWC());
if (args.size() > 1) {
const auto name = String8(args[1]);
@@ -4458,7 +4449,7 @@
mPhaseConfiguration->dump(result);
StringAppendF(&result,
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
- dispSyncPresentTimeOffset, getVsyncPeriod());
+ dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy();
StringAppendF(&result,
@@ -4563,7 +4554,8 @@
if (!displayId) {
continue;
}
- const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId);
+ const auto hwcDisplayId =
+ getHwComposer().fromPhysicalDisplayId(static_cast<PhysicalDisplayId>(*displayId));
if (!hwcDisplayId) {
continue;
}
@@ -4970,7 +4962,7 @@
return OK;
}
case CAPTURE_LAYERS:
- case CAPTURE_SCREEN:
+ case CAPTURE_DISPLAY:
case ADD_REGION_SAMPLING_LISTENER:
case REMOVE_REGION_SAMPLING_LISTENER: {
// codes that require permission check
@@ -4984,7 +4976,7 @@
}
return OK;
}
- case CAPTURE_SCREEN_BY_ID: {
+ case CAPTURE_DISPLAY_BY_ID: {
IPCThreadState* ipc = IPCThreadState::self();
const int uid = ipc->getCallingUid();
if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
@@ -5323,7 +5315,8 @@
case 1035: {
n = data.readInt32();
mDebugDisplayConfigSetByBackdoor = false;
- if (n >= 0) {
+ const auto numConfigs = mRefreshRateConfigs->getAllRefreshRates().size();
+ if (n >= 0 && n < numConfigs) {
const auto displayToken = getInternalDisplayToken();
status_t result = setActiveConfig(displayToken, n);
if (result != NO_ERROR) {
@@ -5429,51 +5422,6 @@
const int mApi;
};
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken,
- sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers,
- Dataspace reqDataspace, ui::PixelFormat reqPixelFormat,
- const Rect& sourceCrop, uint32_t reqWidth,
- uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, bool captureSecureLayers) {
- ATRACE_CALL();
-
- if (!displayToken) return BAD_VALUE;
-
- auto renderAreaRotation = ui::Transform::toRotationFlags(rotation);
- if (renderAreaRotation == ui::Transform::ROT_INVALID) {
- ALOGE("%s: Invalid rotation: %s", __FUNCTION__, toCString(rotation));
- renderAreaRotation = ui::Transform::ROT_0;
- }
-
- wp<DisplayDevice> displayWeak;
- ui::LayerStack layerStack;
- ui::Size reqSize(reqWidth, reqHeight);
- {
- Mutex::Autolock lock(mStateLock);
- sp<DisplayDevice> display = getDisplayDeviceLocked(displayToken);
- if (!display) return NAME_NOT_FOUND;
- displayWeak = display;
- layerStack = display->getLayerStack();
-
- // set the requested width/height to the logical display viewport size
- // by default
- if (reqWidth == 0 || reqHeight == 0) {
- reqSize = display->getViewport().getSize();
- }
- }
-
- RenderAreaFuture renderAreaFuture = promise::defer([=] {
- return DisplayRenderArea::create(displayWeak, sourceCrop, reqSize, reqDataspace,
- renderAreaRotation, captureSecureLayers);
- });
-
- auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) {
- traverseLayersInLayerStack(layerStack, visitor);
- };
- return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, outBuffer,
- reqPixelFormat, useIdentityTransform, outCapturedSecureLayers);
-}
-
static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) {
switch (colorMode) {
case ColorMode::DISPLAY_P3:
@@ -5486,6 +5434,51 @@
}
}
+status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
+ ScreenCaptureResults& captureResults) {
+ ATRACE_CALL();
+
+ if (!args.displayToken) return BAD_VALUE;
+
+ auto renderAreaRotation = ui::Transform::toRotationFlags(args.rotation);
+ if (renderAreaRotation == ui::Transform::ROT_INVALID) {
+ ALOGE("%s: Invalid rotation: %s", __FUNCTION__, toCString(args.rotation));
+ renderAreaRotation = ui::Transform::ROT_0;
+ }
+
+ wp<DisplayDevice> displayWeak;
+ ui::LayerStack layerStack;
+ ui::Size reqSize(args.width, args.height);
+ ui::Dataspace dataspace;
+ {
+ Mutex::Autolock lock(mStateLock);
+ sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken);
+ if (!display) return NAME_NOT_FOUND;
+ displayWeak = display;
+ layerStack = display->getLayerStack();
+
+ // set the requested width/height to the logical display viewport size
+ // by default
+ if (args.width == 0 || args.height == 0) {
+ reqSize = display->getViewport().getSize();
+ }
+
+ const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode;
+ dataspace = pickDataspaceFromColorMode(colorMode);
+ }
+
+ RenderAreaFuture renderAreaFuture = promise::defer([=] {
+ return DisplayRenderArea::create(displayWeak, args.sourceCrop, reqSize, dataspace,
+ renderAreaRotation, args.captureSecureLayers);
+ });
+
+ auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) {
+ traverseLayersInLayerStack(layerStack, visitor);
+ };
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
+ args.pixelFormat, args.useIdentityTransform, captureResults);
+}
+
status_t SurfaceFlinger::setSchedFifo(bool enabled) {
static constexpr int kFifoPriority = 2;
static constexpr int kOtherPriority = 0;
@@ -5507,8 +5500,8 @@
}
sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
- const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
- if (displayToken) {
+ if (const sp<IBinder> displayToken =
+ getPhysicalDisplayTokenLocked(PhysicalDisplayId{displayOrLayerStack})) {
return getDisplayDeviceLocked(displayToken);
}
// Couldn't find display by displayId. Try to get display by layerStack since virtual displays
@@ -5525,12 +5518,13 @@
return nullptr;
}
-status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* outDataspace,
- sp<GraphicBuffer>* outBuffer) {
+status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack,
+ ScreenCaptureResults& captureResults) {
ui::LayerStack layerStack;
wp<DisplayDevice> displayWeak;
ui::Size size;
ui::Transform::RotationFlags captureOrientation;
+ ui::Dataspace dataspace;
{
Mutex::Autolock lock(mStateLock);
sp<DisplayDevice> display = getDisplayByIdOrLayerStack(displayOrLayerStack);
@@ -5562,42 +5556,39 @@
default:
break;
}
- *outDataspace =
+ dataspace =
pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode);
}
RenderAreaFuture renderAreaFuture = promise::defer([=] {
- return DisplayRenderArea::create(displayWeak, Rect(), size, *outDataspace,
- captureOrientation, false /* captureSecureLayers */);
+ return DisplayRenderArea::create(displayWeak, Rect(), size,
+ captureResults.capturedDataspace, captureOrientation,
+ false /* captureSecureLayers */);
});
auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) {
traverseLayersInLayerStack(layerStack, visitor);
};
- bool ignored = false;
-
- return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, outBuffer,
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
ui::PixelFormat::RGBA_8888, false /* useIdentityTransform */,
- ignored /* outCapturedSecureLayers */);
+ captureResults);
}
-status_t SurfaceFlinger::captureLayers(
- const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
- const Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& excludeHandles,
- float frameScale, bool childrenOnly) {
+status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
+ ScreenCaptureResults& captureResults) {
ATRACE_CALL();
ui::Size reqSize;
sp<Layer> parent;
- Rect crop(sourceCrop);
+ Rect crop(args.sourceCrop);
std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
Rect displayViewport;
+ ui::Dataspace dataspace;
{
Mutex::Autolock lock(mStateLock);
- parent = fromHandleLocked(layerHandleBinder).promote();
+ parent = fromHandleLocked(args.layerHandle).promote();
if (parent == nullptr || parent->isRemovedFromCurrentState()) {
ALOGE("captureLayers called with an invalid or removed parent");
return NAME_NOT_FOUND;
@@ -5611,24 +5602,24 @@
}
Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getCurrentState());
- if (sourceCrop.width() <= 0) {
+ if (args.sourceCrop.width() <= 0) {
crop.left = 0;
crop.right = parentSourceBounds.getWidth();
}
- if (sourceCrop.height() <= 0) {
+ if (args.sourceCrop.height() <= 0) {
crop.top = 0;
crop.bottom = parentSourceBounds.getHeight();
}
- if (crop.isEmpty() || frameScale <= 0.0f) {
+ if (crop.isEmpty() || args.frameScale <= 0.0f) {
// Error out if the layer has no source bounds (i.e. they are boundless) and a source
// crop was not specified, or an invalid frame scale was provided.
return BAD_VALUE;
}
- reqSize = ui::Size(crop.width() * frameScale, crop.height() * frameScale);
+ reqSize = ui::Size(crop.width() * args.frameScale, crop.height() * args.frameScale);
- for (const auto& handle : excludeHandles) {
+ for (const auto& handle : args.excludeHandles) {
sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
if (excludeLayer != nullptr) {
excludeLayers.emplace(excludeLayer);
@@ -5644,6 +5635,9 @@
}
displayViewport = display->getViewport();
+
+ const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode;
+ dataspace = pickDataspaceFromColorMode(colorMode);
} // mStateLock
// really small crop or frameScale
@@ -5654,8 +5648,10 @@
reqSize.height = 1;
}
+ bool childrenOnly = args.childrenOnly;
+
RenderAreaFuture renderAreaFuture = promise::defer([=]() -> std::unique_ptr<RenderArea> {
- return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, reqDataspace,
+ return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace,
childrenOnly, displayViewport);
});
@@ -5680,36 +5676,34 @@
});
};
- bool outCapturedSecureLayers = false;
- return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, outBuffer,
- reqPixelFormat, false, outCapturedSecureLayers);
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
+ args.pixelFormat, false, captureResults);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
- ui::Size bufferSize, sp<GraphicBuffer>* outBuffer,
- ui::PixelFormat reqPixelFormat,
+ ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
bool useIdentityTransform,
- bool& outCapturedSecureLayers) {
+ ScreenCaptureResults& captureResults) {
ATRACE_CALL();
// TODO(b/116112787) Make buffer usage a parameter.
const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
- *outBuffer = getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
- static_cast<android_pixel_format>(reqPixelFormat),
- 1, usage, "screenshot");
+ sp<GraphicBuffer> buffer =
+ getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
+ static_cast<android_pixel_format>(reqPixelFormat),
+ 1 /* layerCount */, usage, "screenshot");
- return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, *outBuffer,
- useIdentityTransform, false /* regionSampling */,
- outCapturedSecureLayers);
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
+ useIdentityTransform, false /* regionSampling */, captureResults);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer,
bool useIdentityTransform, bool regionSampling,
- bool& outCapturedSecureLayers) {
+ ScreenCaptureResults& captureResults) {
const int uid = IPCThreadState::self()->getCallingUid();
const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
@@ -5734,9 +5728,9 @@
Mutex::Autolock lock(mStateLock);
renderArea->render([&] {
- result = captureScreenImplLocked(*renderArea, traverseLayers, buffer.get(),
- useIdentityTransform, forSystem, &fd,
- regionSampling, outCapturedSecureLayers);
+ result = renderScreenImplLocked(*renderArea, traverseLayers, buffer.get(),
+ useIdentityTransform, forSystem, &fd,
+ regionSampling, captureResults);
});
return {result, fd};
@@ -5751,13 +5745,30 @@
return result;
}
-void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
- TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer,
- bool useIdentityTransform, bool regionSampling,
- int* outSyncFd) {
+status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<GraphicBuffer>& buffer,
+ bool useIdentityTransform, bool forSystem,
+ int* outSyncFd, bool regionSampling,
+ ScreenCaptureResults& captureResults) {
ATRACE_CALL();
+ traverseLayers([&](Layer* layer) {
+ captureResults.capturedSecureLayers =
+ captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure());
+ });
+
+ // We allow the system server to take screenshots of secure layers for
+ // use in situations like the Screen-rotation animation and place
+ // the impetus on WindowManager to not persist them.
+ if (captureResults.capturedSecureLayers && !forSystem) {
+ ALOGW("FB is protected: PERMISSION_DENIED");
+ return PERMISSION_DENIED;
+ }
+
+ captureResults.buffer = buffer;
+ captureResults.capturedDataspace = renderArea.getReqDataSpace();
+
const auto reqWidth = renderArea.getReqWidth();
const auto reqHeight = renderArea.getReqHeight();
const auto sourceCrop = renderArea.getSourceCrop();
@@ -5849,30 +5860,7 @@
layer->onLayerDisplayed(releaseFence);
}
}
-}
-status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
- TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer,
- bool useIdentityTransform, bool forSystem,
- int* outSyncFd, bool regionSampling,
- bool& outCapturedSecureLayers) {
- ATRACE_CALL();
-
- traverseLayers([&](Layer* layer) {
- outCapturedSecureLayers =
- outCapturedSecureLayers || (layer->isVisible() && layer->isSecure());
- });
-
- // We allow the system server to take screenshots of secure layers for
- // use in situations like the Screen-rotation animation and place
- // the impetus on WindowManager to not persist them.
- if (outCapturedSecureLayers && !forSystem) {
- ALOGW("FB is protected: PERMISSION_DENIED");
- return PERMISSION_DENIED;
- }
- renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, regionSampling,
- outSyncFd);
return NO_ERROR;
}
@@ -5954,7 +5942,9 @@
const nsecs_t vsyncPeriod = getHwComposer()
.getConfigs(*displayId)[policy->defaultConfig.value()]
->getVsyncPeriod();
- mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
+ mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle,
+ static_cast<PhysicalDisplayId>(
+ *display->getId()),
policy->defaultConfig, vsyncPeriod);
return NO_ERROR;
}
@@ -5986,7 +5976,8 @@
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig())
.getVsyncPeriod();
- mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
+ mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle,
+ static_cast<PhysicalDisplayId>(*display->getId()),
display->getActiveConfig(), vsyncPeriod);
toggleKernelIdleTimer();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d56321d..6c00931 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -300,13 +300,6 @@
// utility function to delete a texture on the main thread
void deleteTextureAsync(uint32_t texture);
- // enable/disable h/w composer event
- // TODO: this should be made accessible only to EventThread
- void setPrimaryVsyncEnabled(bool enabled);
-
- // main thread function to enable/disable h/w composer event
- void setPrimaryVsyncEnabledInternal(bool enabled) REQUIRES(mStateLock);
-
// called on the main thread by MessageQueue when an internal message
// is received
// TODO: this should be made accessible only to MessageQueue
@@ -433,19 +426,12 @@
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
ISurfaceComposer::ConfigChanged configChanged =
ISurfaceComposer::eConfigChangedSuppress) override;
- status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
- bool& outCapturedSecureLayers, ui::Dataspace reqDataspace,
- ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
- ui::Rotation rotation, bool captureSecureLayers) override;
- status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace,
- sp<GraphicBuffer>* outBuffer) override;
- status_t captureLayers(
- const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
- const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
- const Rect& sourceCrop,
- const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& exclude,
- float frameScale, bool childrenOnly) override;
+ status_t captureDisplay(const DisplayCaptureArgs& args,
+ ScreenCaptureResults& captureResults) override;
+ status_t captureDisplay(uint64_t displayOrLayerStack,
+ ScreenCaptureResults& captureResults) override;
+ status_t captureLayers(const LayerCaptureArgs& args,
+ ScreenCaptureResults& captureResults) override;
status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*) override;
@@ -535,8 +521,12 @@
/* ------------------------------------------------------------------------
* ISchedulerCallback
*/
+
+ // Toggles hardware VSYNC by calling into HWC.
+ void setVsyncEnabled(bool) override;
+ // Initiates a refresh rate change to be applied on invalidate.
void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override;
- // force full composition on all displays without resetting the scheduler idle timer.
+ // Forces full composition on all displays without resetting the scheduler idle timer.
void repaintEverythingForHWC() override;
// Called when kernel idle timer has expired. Used to update the refresh rate overlay.
void kernelTimerChanged(bool expired) override;
@@ -549,6 +539,7 @@
bool mSupportKernelIdleTimer = false;
// Show spinner with refresh rate overlay
bool mRefreshRateOverlaySpinner = false;
+
/* ------------------------------------------------------------------------
* Message handling
*/
@@ -613,7 +604,7 @@
void updateInputWindowInfo();
void commitInputWindowCommands() REQUIRES(mStateLock);
void updateCursorAsync();
- void initScheduler(DisplayId primaryDisplayId);
+ void initScheduler(PhysicalDisplayId primaryDisplayId);
/* handlePageFlip - latch a new buffer if available and compute the dirty
* region. Returns whether a new buffer has been latched, i.e., whether it
@@ -726,22 +717,20 @@
using TraverseLayersFunction = std::function<void(const LayerVector::Visitor&)>;
using RenderAreaFuture = std::future<std::unique_ptr<RenderArea>>;
- void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
- bool regionSampling, int* outSyncFd);
+ status_t renderScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
+ bool forSystem, int* outSyncFd, bool regionSampling,
+ ScreenCaptureResults& captureResults);
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize,
- sp<GraphicBuffer>* outBuffer, ui::PixelFormat,
- bool useIdentityTransform, bool& outCapturedSecureLayers);
+ ui::PixelFormat, bool useIdentityTransform,
+ ScreenCaptureResults& captureResults);
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, const sp<GraphicBuffer>&,
bool useIdentityTransform, bool regionSampling,
- bool& outCapturedSecureLayers);
+ ScreenCaptureResults& captureResults);
sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
- status_t captureScreenImplLocked(const RenderArea& renderArea,
- TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
- bool forSystem, int* outSyncFd, bool regionSampling,
- bool& outCapturedSecureLayers);
+
void traverseLayersInLayerStack(ui::LayerStack, const LayerVector::Visitor&);
sp<StartPropertySetThread> mStartPropertySetThread;
@@ -856,7 +845,7 @@
/* ------------------------------------------------------------------------
* VSync
*/
- nsecs_t getVsyncPeriod() const REQUIRES(mStateLock);
+ nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock);
// Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
@@ -888,7 +877,8 @@
/*
* Display identification
*/
- sp<IBinder> getPhysicalDisplayTokenLocked(DisplayId displayId) const REQUIRES(mStateLock) {
+ sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const
+ REQUIRES(mStateLock) {
const auto it = mPhysicalDisplayTokens.find(displayId);
return it != mPhysicalDisplayTokens.end() ? it->second : nullptr;
}
@@ -909,7 +899,7 @@
return displayId ? getPhysicalDisplayTokenLocked(*displayId) : nullptr;
}
- std::optional<DisplayId> getInternalDisplayIdLocked() const REQUIRES(mStateLock) {
+ std::optional<PhysicalDisplayId> getInternalDisplayIdLocked() const REQUIRES(mStateLock) {
const auto hwcDisplayId = getHwComposer().getInternalHwcDisplayId();
return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
}
@@ -1078,7 +1068,8 @@
// this may only be written from the main thread with mStateLock held
// it may be read from other threads with mStateLock held
std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock);
- std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens GUARDED_BY(mStateLock);
+ std::unordered_map<PhysicalDisplayId, sp<IBinder>> mPhysicalDisplayTokens
+ GUARDED_BY(mStateLock);
std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken GUARDED_BY(mStateLock);
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index ddd20a5..025d1a4 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -38,7 +38,6 @@
#include "DisplayHardware/ComposerHal.h"
#include "Scheduler/DispSync.h"
-#include "Scheduler/EventControlThread.h"
#include "Scheduler/MessageQueue.h"
#include "Scheduler/PhaseOffsets.h"
#include "Scheduler/Scheduler.h"
@@ -51,11 +50,6 @@
return std::make_unique<android::impl::DispSync>(name, hasSyncFramework);
}
-std::unique_ptr<EventControlThread> DefaultFactory::createEventControlThread(
- SetVSyncEnabled setVSyncEnabled) {
- return std::make_unique<android::impl::EventControlThread>(std::move(setVSyncEnabled));
-}
-
std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
return std::make_unique<android::impl::HWComposer>(serviceName);
}
@@ -74,11 +68,8 @@
}
std::unique_ptr<Scheduler> DefaultFactory::createScheduler(
- SetVSyncEnabled setVSyncEnabled, const scheduler::RefreshRateConfigs& configs,
- ISchedulerCallback& schedulerCallback) {
- return std::make_unique<Scheduler>(std::move(setVSyncEnabled), configs, schedulerCallback,
- property_get_bool("debug.sf.use_content_detection_v2", true),
- sysprop::use_content_detection_for_refresh_rate(false));
+ const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) {
+ return std::make_unique<Scheduler>(configs, callback);
}
std::unique_ptr<SurfaceInterceptor> DefaultFactory::createSurfaceInterceptor(
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index bd40cfb..1757fa8 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -27,13 +27,11 @@
virtual ~DefaultFactory();
std::unique_ptr<DispSync> createDispSync(const char* name, bool hasSyncFramework) override;
- std::unique_ptr<EventControlThread> createEventControlThread(SetVSyncEnabled) override;
std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) override;
std::unique_ptr<MessageQueue> createMessageQueue() override;
std::unique_ptr<scheduler::PhaseConfiguration> createPhaseConfiguration(
const scheduler::RefreshRateConfigs&) override;
- std::unique_ptr<Scheduler> createScheduler(SetVSyncEnabled,
- const scheduler::RefreshRateConfigs&,
+ std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&,
ISchedulerCallback&) override;
std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) override;
sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 6f4fcc6..1d710c4 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -35,12 +35,10 @@
class ContainerLayer;
class DisplayDevice;
class DispSync;
-class EventControlThread;
class GraphicBuffer;
class HWComposer;
class IGraphicBufferConsumer;
class IGraphicBufferProducer;
-class ISchedulerCallback;
class Layer;
class MessageQueue;
class Scheduler;
@@ -49,6 +47,7 @@
class SurfaceInterceptor;
struct DisplayDeviceCreationArgs;
+struct ISchedulerCallback;
struct LayerCreationArgs;
namespace compositionengine {
@@ -68,16 +67,12 @@
// of each interface.
class Factory {
public:
- using SetVSyncEnabled = std::function<void(bool)>;
-
virtual std::unique_ptr<DispSync> createDispSync(const char* name, bool hasSyncFramework) = 0;
- virtual std::unique_ptr<EventControlThread> createEventControlThread(SetVSyncEnabled) = 0;
virtual std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) = 0;
virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;
virtual std::unique_ptr<scheduler::PhaseConfiguration> createPhaseConfiguration(
const scheduler::RefreshRateConfigs&) = 0;
- virtual std::unique_ptr<Scheduler> createScheduler(SetVSyncEnabled,
- const scheduler::RefreshRateConfigs&,
+ virtual std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&,
ISchedulerCallback&) = 0;
virtual std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) = 0;
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index c96dfc7..719c46e 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -27,6 +27,7 @@
"InvalidHandles_test.cpp",
"LayerCallback_test.cpp",
"LayerRenderTypeTransaction_test.cpp",
+ "LayerState_test.cpp",
"LayerTransaction_test.cpp",
"LayerTypeAndRenderTypeTransaction_test.cpp",
"LayerTypeTransaction_test.cpp",
@@ -34,6 +35,7 @@
"MirrorLayer_test.cpp",
"MultiDisplayLayerBounds_test.cpp",
"RelativeZ_test.cpp",
+ "ScreenCapture_test.cpp",
"SetFrameRate_test.cpp",
"SetGeometry_test.cpp",
"Stress_test.cpp",
diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp
index 293738c..4868c12 100644
--- a/services/surfaceflinger/tests/BufferGenerator.cpp
+++ b/services/surfaceflinger/tests/BufferGenerator.cpp
@@ -88,7 +88,7 @@
sp<Surface> mSurface;
};
-/* Used to generate valid fences. It is not possible to create a dummy sync
+/* Used to generate valid fences. It is not possible to create a placeholder sync
* fence for testing. Egl can generate buffers along with a valid fence.
* The buffer cannot be guaranteed to be the same format across all devices so
* a CPU filled buffer is used instead. The Egl fence is used along with the
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index c136708..10a517e 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -18,7 +18,6 @@
namespace {
const String8 DISPLAY_NAME("Credentials Display Test");
const String8 SURFACE_NAME("Test Surface Name");
-const float FRAME_SCALE = 1.0f;
} // namespace
/**
@@ -260,9 +259,10 @@
const auto display = SurfaceComposerClient::getInternalDisplayToken();
std::function<status_t()> condition = [=]() {
sp<GraphicBuffer> outBuffer;
- return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
- 0 /*reqHeight*/, false, ui::ROTATION_0, &outBuffer);
+ DisplayCaptureArgs captureArgs;
+ captureArgs.displayToken = display;
+ ScreenCaptureResults captureResults;
+ return ScreenshotClient::captureDisplay(captureArgs, captureResults);
};
ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
}
@@ -271,10 +271,12 @@
setupBackgroundSurface();
sp<GraphicBuffer> outBuffer;
std::function<status_t()> condition = [=]() {
- sp<GraphicBuffer> outBuffer;
- return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
- Rect(0, 0, 1, 1), FRAME_SCALE, &outBuffer);
+ LayerCaptureArgs captureArgs;
+ captureArgs.layerHandle = mBGSurfaceControl->getHandle();
+ captureArgs.sourceCrop = {0, 0, 1, 1};
+
+ ScreenCaptureResults captureResults;
+ return ScreenshotClient::captureLayers(captureArgs, captureResults);
};
ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
}
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
index 42d1f5a..300e9c7 100644
--- a/services/surfaceflinger/tests/InvalidHandles_test.cpp
+++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp
@@ -57,10 +57,12 @@
TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NAME_NOT_FOUND,
- sf->captureLayers(mNotSc->getHandle(), &outBuffer, Rect::EMPTY_RECT, 1.0f));
+ LayerCaptureArgs args;
+ args.layerHandle = mNotSc->getHandle();
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(args, captureResults));
}
} // namespace
diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp
new file mode 100644
index 0000000..8a49e77
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerState_test.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <binder/Binder.h>
+#include <binder/Parcel.h>
+
+#include <gui/LayerState.h>
+
+namespace android {
+namespace test {
+
+TEST(LayerStateTest, ParcellingDisplayCaptureArgs) {
+ DisplayCaptureArgs args;
+ args.pixelFormat = ui::PixelFormat::RGB_565;
+ args.sourceCrop = Rect(0, 0, 500, 200);
+ args.frameScale = 2;
+ args.captureSecureLayers = true;
+ args.displayToken = new BBinder();
+ args.width = 10;
+ args.height = 20;
+ args.useIdentityTransform = true;
+ args.rotation = ui::ROTATION_90;
+
+ Parcel p;
+ args.write(p);
+ p.setDataPosition(0);
+
+ DisplayCaptureArgs args2;
+ args2.read(p);
+
+ ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
+ ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
+ ASSERT_EQ(args.frameScale, args2.frameScale);
+ ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
+ ASSERT_EQ(args.displayToken, args2.displayToken);
+ ASSERT_EQ(args.width, args2.width);
+ ASSERT_EQ(args.height, args2.height);
+ ASSERT_EQ(args.useIdentityTransform, args2.useIdentityTransform);
+ ASSERT_EQ(args.rotation, args2.rotation);
+}
+
+TEST(LayerStateTest, ParcellingLayerCaptureArgs) {
+ LayerCaptureArgs args;
+ args.pixelFormat = ui::PixelFormat::RGB_565;
+ args.sourceCrop = Rect(0, 0, 500, 200);
+ args.frameScale = 2;
+ args.captureSecureLayers = true;
+ args.layerHandle = new BBinder();
+ args.excludeHandles = {new BBinder(), new BBinder()};
+ args.childrenOnly = false;
+
+ Parcel p;
+ args.write(p);
+ p.setDataPosition(0);
+
+ LayerCaptureArgs args2;
+ args2.read(p);
+
+ ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
+ ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
+ ASSERT_EQ(args.frameScale, args2.frameScale);
+ ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
+ ASSERT_EQ(args.layerHandle, args2.layerHandle);
+ ASSERT_EQ(args.excludeHandles, args2.excludeHandles);
+ ASSERT_EQ(args.childrenOnly, args2.childrenOnly);
+}
+
+TEST(LayerStateTest, ParcellingScreenCaptureResults) {
+ ScreenCaptureResults results;
+ results.buffer = new GraphicBuffer(100, 200, PIXEL_FORMAT_RGBA_8888, 1, 0);
+ results.capturedSecureLayers = true;
+ results.capturedDataspace = ui::Dataspace::DISPLAY_P3;
+
+ Parcel p;
+ results.write(p);
+ p.setDataPosition(0);
+
+ ScreenCaptureResults results2;
+ results2.read(p);
+
+ // GraphicBuffer object is reallocated so compare the data in the graphic buffer
+ // rather than the object itself
+ ASSERT_EQ(results.buffer->getWidth(), results2.buffer->getWidth());
+ ASSERT_EQ(results.buffer->getHeight(), results2.buffer->getHeight());
+ ASSERT_EQ(results.buffer->getPixelFormat(), results2.buffer->getPixelFormat());
+ ASSERT_EQ(results.capturedSecureLayers, results2.capturedSecureLayers);
+ ASSERT_EQ(results.capturedDataspace, results2.capturedDataspace);
+}
+
+} // namespace test
+} // namespace android
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index f3e11d8..d4e952a 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -40,6 +40,8 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed));
+
+ mCaptureArgs.displayToken = mDisplay;
}
virtual void TearDown() {
@@ -249,6 +251,9 @@
sp<SurfaceControl> mBlackBgSurface;
bool mColorManagementUsed;
+ DisplayCaptureArgs mCaptureArgs;
+ ScreenCaptureResults mCaptureResults;
+
private:
void SetUpDisplay() {
mDisplay = mClient->getInternalDisplayToken();
diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp
index 97cba63..0ef4150 100644
--- a/services/surfaceflinger/tests/LayerTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp
@@ -32,18 +32,16 @@
ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
sp<ISurfaceComposer> composer = ComposerService::getComposerService();
- sp<GraphicBuffer> outBuffer;
Transaction()
.setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
.apply(true);
- ASSERT_EQ(PERMISSION_DENIED,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+ ASSERT_EQ(PERMISSION_DENIED, composer->captureDisplay(mCaptureArgs, mCaptureResults));
UIDFaker f(AID_SYSTEM);
// By default the system can capture screenshots with secure layers but they
// will be blacked out
- ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+ ASSERT_EQ(NO_ERROR, composer->captureDisplay(mCaptureArgs, mCaptureResults));
{
SCOPED_TRACE("as system");
@@ -53,13 +51,12 @@
// Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
// to receive them...we are expected to take care with the results.
- bool outCapturedSecureLayers;
- ASSERT_EQ(NO_ERROR,
- composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers,
- ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0,
- 0, false, ui::ROTATION_0, true));
- ASSERT_EQ(true, outCapturedSecureLayers);
- ScreenCapture sc(outBuffer);
+ DisplayCaptureArgs args;
+ args.displayToken = mDisplay;
+ args.captureSecureLayers = true;
+ ASSERT_EQ(NO_ERROR, composer->captureDisplay(args, mCaptureResults));
+ ASSERT_EQ(true, mCaptureResults.capturedSecureLayers);
+ ScreenCapture sc(mCaptureResults.buffer);
sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
}
@@ -118,10 +115,9 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
const auto producer = layer->getIGraphicBufferProducer();
- const sp<IProducerListener> dummyListener(new DummyProducerListener);
+ const sp<IProducerListener> stubListener(new StubProducerListener);
IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
- ASSERT_EQ(OK,
- producer->connect(dummyListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput));
+ ASSERT_EQ(OK, producer->connect(stubListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput));
std::map<int, sp<GraphicBuffer>> slotMap;
auto slotToBuffer = [&](int slot, sp<GraphicBuffer>* buf) {
diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
index 84780ba..2ec4ea4 100644
--- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
@@ -170,11 +170,15 @@
Transaction()
.setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
.apply(true);
- ASSERT_EQ(PERMISSION_DENIED,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+
+ DisplayCaptureArgs args;
+ args.displayToken = mDisplay;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(PERMISSION_DENIED, composer->captureDisplay(args, captureResults));
Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
- ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false));
+ ASSERT_EQ(NO_ERROR, composer->captureDisplay(args, captureResults));
}
TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) {
sp<SurfaceControl> layer;
diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp
index 84823f5..c56d473 100644
--- a/services/surfaceflinger/tests/LayerUpdate_test.cpp
+++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp
@@ -1084,432 +1084,6 @@
}
}
-class ScreenCaptureTest : public LayerUpdateTest {
-protected:
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
- auto bgHandle = mBGSurfaceControl->getHandle();
- ScreenCapture::captureLayers(&mCapture, bgHandle);
- mCapture->expectBGColor(0, 0);
- // Doesn't capture FG layer which is at 64, 64
- mCapture->expectBGColor(64, 64);
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- // Captures mFGSurfaceControl layer and its child.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- mCapture->expectChildColor(0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- // Captures mFGSurfaceControl's child
- ScreenCapture::captureChildLayers(&mCapture, fgHandle);
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->expectChildColor(0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerExclude) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- .show(child2)
- .setLayer(child, 1)
- .setLayer(child2, 2)
- .apply(true);
-
- // Child2 would be visible but its excluded, so we should see child1 color instead.
- ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->checkPixel(0, 0, 200, 200, 200);
-}
-
-// Like the last test but verifies that children are also exclude.
-TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
- sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, child2.get());
- TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- .show(child2)
- .show(child3)
- .setLayer(child, 1)
- .setLayer(child2, 2)
- .apply(true);
-
- // Child2 would be visible but its excluded, so we should see child1 color instead.
- ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->checkPixel(0, 0, 200, 200, 200);
-}
-
-TEST_F(ScreenCaptureTest, CaptureTransparent) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
-
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- auto childHandle = child->getHandle();
-
- // Captures child
- ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
- mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
- // Area outside of child's bounds is transparent.
- mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
-}
-
-TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- ASSERT_NE(nullptr, child.get()) << "failed to create surface";
- sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0);
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- // Set relative layer above fg layer so should be shown above when computing all layers.
- .setRelativeLayer(relative, fgHandle, 1)
- .show(relative)
- .apply(true);
-
- // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- mCapture->expectChildColor(0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- // Set relative layer below fg layer but relative to child layer so it should be shown
- // above child layer.
- .setLayer(relative, -1)
- .setRelativeLayer(relative, child->getHandle(), 1)
- .show(relative)
- .apply(true);
-
- // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its
- // relative value should be taken into account, placing it above child layer.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- // Relative layer is showing on top of child layer
- mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
-}
-
-TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithSourceCrop) {
- sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<GraphicBuffer> outBuffer;
- Rect sourceCrop(0, 0, 10, 10);
- ASSERT_EQ(NO_ERROR, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
- ScreenCapture sc(outBuffer);
-
- sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
-}
-
-TEST_F(ScreenCaptureTest, CaptureBoundedLayerWithoutSourceCrop) {
- sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
- Rect layerCrop(0, 0, 10, 10);
- SurfaceComposerClient::Transaction().setCrop_legacy(child, layerCrop).show(child).apply(true);
-
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<GraphicBuffer> outBuffer;
- Rect sourceCrop = Rect();
- ASSERT_EQ(NO_ERROR, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
- ScreenCapture sc(outBuffer);
-
- sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
-}
-
-TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithoutSourceCropFails) {
- sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<GraphicBuffer> outBuffer;
- Rect sourceCrop = Rect();
-
- ASSERT_EQ(BAD_VALUE, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
-}
-
-TEST_F(ScreenCaptureTest, CaptureBufferLayerWithoutBufferFails) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- SurfaceComposerClient::Transaction().show(child).apply(true);
-
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<GraphicBuffer> outBuffer;
- Rect sourceCrop = Rect();
- ASSERT_EQ(BAD_VALUE, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
-
- TransactionUtils::fillSurfaceRGBA8(child, Color::RED);
- SurfaceComposerClient::Transaction().apply(true);
- ASSERT_EQ(NO_ERROR, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
- ScreenCapture sc(outBuffer);
- sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
-}
-
-// In the following tests we verify successful skipping of a parent layer,
-// so we use the same verification logic and only change how we mutate
-// the parent layer to verify that various properties are ignored.
-class ScreenCaptureChildOnlyTest : public LayerUpdateTest {
-public:
- void SetUp() override {
- LayerUpdateTest::SetUp();
-
- mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
- mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
-
- SurfaceComposerClient::Transaction().show(mChild).apply(true);
- }
-
- void verify(std::function<void()> verifyStartingState) {
- // Verify starting state before a screenshot is taken.
- verifyStartingState();
-
- // Verify child layer does not inherit any of the properties of its
- // parent when its screenshot is captured.
- auto fgHandle = mFGSurfaceControl->getHandle();
- ScreenCapture::captureChildLayers(&mCapture, fgHandle);
- mCapture->checkPixel(10, 10, 0, 0, 0);
- mCapture->expectChildColor(0, 0);
-
- // Verify all assumptions are still true after the screenshot is taken.
- verifyStartingState();
- }
-
- std::unique_ptr<ScreenCapture> mCapture;
- sp<SurfaceControl> mChild;
-};
-
-// Regression test b/76099859
-TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) {
- SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
-
- // Even though the parent is hidden we should still capture the child.
-
- // Before and after reparenting, verify child is properly hidden
- // when rendering full-screen.
- verify([&] { screenshot()->expectBGColor(64, 64); });
-}
-
-TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) {
- SurfaceComposerClient::Transaction()
- .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1))
- .apply(true);
-
- // Even though the parent is cropped out we should still capture the child.
-
- // Before and after reparenting, verify child is cropped by parent.
- verify([&] { screenshot()->expectBGColor(65, 65); });
-}
-
-// Regression test b/124372894
-TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) {
- SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true);
-
- // We should not inherit the parent scaling.
-
- // Before and after reparenting, verify child is properly scaled.
- verify([&] { screenshot()->expectChildColor(80, 80); });
-}
-
-TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
- auto fgHandle = mFGSurfaceControl->getHandle();
-
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
-
- sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
- PIXEL_FORMAT_RGBA_8888, 0, child.get());
-
- TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
- SurfaceComposerClient::Transaction()
- .show(child)
- .setPosition(grandchild, 5, 5)
- .show(grandchild)
- .apply(true);
-
- // Captures mFGSurfaceControl, its child, and the grandchild.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
- mCapture->expectFGColor(10, 10);
- mCapture->expectChildColor(0, 0);
- mCapture->checkPixel(5, 5, 50, 50, 50);
-}
-
-TEST_F(ScreenCaptureTest, CaptureChildOnly) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- auto childHandle = child->getHandle();
-
- SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
-
- // Captures only the child layer, and not the parent.
- ScreenCapture::captureLayers(&mCapture, childHandle);
- mCapture->expectChildColor(0, 0);
- mCapture->expectChildColor(9, 9);
-}
-
-TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
- sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
- TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
- auto childHandle = child->getHandle();
-
- sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
- PIXEL_FORMAT_RGBA_8888, 0, child.get());
- TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
-
- SurfaceComposerClient::Transaction()
- .show(child)
- .setPosition(grandchild, 5, 5)
- .show(grandchild)
- .apply(true);
-
- auto grandchildHandle = grandchild->getHandle();
-
- // Captures only the grandchild.
- ScreenCapture::captureLayers(&mCapture, grandchildHandle);
- mCapture->checkPixel(0, 0, 50, 50, 50);
- mCapture->checkPixel(4, 4, 50, 50, 50);
-}
-
-TEST_F(ScreenCaptureTest, CaptureCrop) {
- sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
- sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
- PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
-
- SurfaceComposerClient::Transaction()
- .setLayer(redLayer, INT32_MAX - 1)
- .show(redLayer)
- .show(blueLayer)
- .apply(true);
-
- auto redLayerHandle = redLayer->getHandle();
-
- // Capturing full screen should have both red and blue are visible.
- ScreenCapture::captureLayers(&mCapture, redLayerHandle);
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
-
- const Rect crop = Rect(0, 0, 30, 30);
- ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
- // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
- // area visible.
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- mCapture->checkPixel(30, 30, 0, 0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureSize) {
- sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
- sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
- PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
-
- SurfaceComposerClient::Transaction()
- .setLayer(redLayer, INT32_MAX - 1)
- .show(redLayer)
- .show(blueLayer)
- .apply(true);
-
- auto redLayerHandle = redLayer->getHandle();
-
- // Capturing full screen should have both red and blue are visible.
- ScreenCapture::captureLayers(&mCapture, redLayerHandle);
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
-
- ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
- // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
- mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
- mCapture->checkPixel(30, 30, 0, 0, 0);
-}
-
-TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
- sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
-
- auto redLayerHandle = redLayer->getHandle();
- Transaction().reparent(redLayer, nullptr).apply();
- redLayer.clear();
- SurfaceComposerClient::Transaction().apply(true);
-
- sp<GraphicBuffer> outBuffer;
-
- // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0));
-}
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
new file mode 100644
index 0000000..2a250ff
--- /dev/null
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include "LayerTransactionTest.h"
+
+namespace android {
+
+class ScreenCaptureTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ const auto display = SurfaceComposerClient::getInternalDisplayToken();
+ ASSERT_FALSE(display == nullptr);
+
+ DisplayConfig config;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ const ui::Size& resolution = config.resolution;
+
+ // Background surface
+ mBGSurfaceControl = createLayer(String8("BG Test Surface"), resolution.getWidth(),
+ resolution.getHeight(), 0);
+ ASSERT_TRUE(mBGSurfaceControl != nullptr);
+ ASSERT_TRUE(mBGSurfaceControl->isValid());
+ TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
+
+ // Foreground surface
+ mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0);
+
+ ASSERT_TRUE(mFGSurfaceControl != nullptr);
+ ASSERT_TRUE(mFGSurfaceControl->isValid());
+
+ TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
+
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, 0);
+
+ t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl);
+
+ t.setLayer(mFGSurfaceControl, INT32_MAX - 1)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .show(mFGSurfaceControl);
+ });
+ }
+
+ virtual void TearDown() {
+ LayerTransactionTest::TearDown();
+ mBGSurfaceControl = 0;
+ mFGSurfaceControl = 0;
+ }
+
+ sp<SurfaceControl> mBGSurfaceControl;
+ sp<SurfaceControl> mFGSurfaceControl;
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
+ auto bgHandle = mBGSurfaceControl->getHandle();
+ ScreenCapture::captureLayers(&mCapture, bgHandle);
+ mCapture->expectBGColor(0, 0);
+ // Doesn't capture FG layer which is at 64, 64
+ mCapture->expectBGColor(64, 64);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ // Captures mFGSurfaceControl layer and its child.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ // Captures mFGSurfaceControl's child
+ ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerExclude) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .show(child2)
+ .setLayer(child, 1)
+ .setLayer(child2, 2)
+ .apply(true);
+
+ // Child2 would be visible but its excluded, so we should see child1 color instead.
+ ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->checkPixel(0, 0, 200, 200, 200);
+}
+
+// Like the last test but verifies that children are also exclude.
+TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
+ sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, child2.get());
+ TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .show(child2)
+ .show(child3)
+ .setLayer(child, 1)
+ .setLayer(child2, 2)
+ .apply(true);
+
+ // Child2 would be visible but its excluded, so we should see child1 color instead.
+ ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()});
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->checkPixel(0, 0, 200, 200, 200);
+}
+
+TEST_F(ScreenCaptureTest, CaptureTransparent) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ auto childHandle = child->getHandle();
+
+ // Captures child
+ ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
+ mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
+ // Area outside of child's bounds is transparent.
+ mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
+}
+
+TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ ASSERT_NE(nullptr, child.get()) << "failed to create surface";
+ sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0);
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ // Set relative layer above fg layer so should be shown above when computing all layers.
+ .setRelativeLayer(relative, fgHandle, 1)
+ .show(relative)
+ .apply(true);
+
+ // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ // Set relative layer below fg layer but relative to child layer so it should be shown
+ // above child layer.
+ .setLayer(relative, -1)
+ .setRelativeLayer(relative, child->getHandle(), 1)
+ .show(relative)
+ .apply(true);
+
+ // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its
+ // relative value should be taken into account, placing it above child layer.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ // Relative layer is showing on top of child layer
+ mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
+}
+
+TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithSourceCrop) {
+ sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ Rect sourceCrop(0, 0, 10, 10);
+ sp<IBinder> childHandle = child->getHandle();
+ ScreenCapture::captureLayers(&mCapture, childHandle, sourceCrop);
+
+ mCapture->expectColor(Rect(0, 0, 9, 9), Color::RED);
+}
+
+TEST_F(ScreenCaptureTest, CaptureBoundedLayerWithoutSourceCrop) {
+ sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
+ Rect layerCrop(0, 0, 10, 10);
+ SurfaceComposerClient::Transaction().setCrop_legacy(child, layerCrop).show(child).apply(true);
+
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<GraphicBuffer> outBuffer;
+ sp<IBinder> childHandle = child->getHandle();
+ ScreenCapture::captureLayers(&mCapture, childHandle);
+
+ mCapture->expectColor(Rect(0, 0, 9, 9), Color::RED);
+}
+
+TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithoutSourceCropFails) {
+ sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+ LayerCaptureArgs args;
+ args.layerHandle = child->getHandle();
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(BAD_VALUE, sf->captureLayers(args, captureResults));
+}
+
+TEST_F(ScreenCaptureTest, CaptureBufferLayerWithoutBufferFails) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<GraphicBuffer> outBuffer;
+
+ LayerCaptureArgs args;
+ args.layerHandle = child->getHandle();
+ args.childrenOnly = false;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(BAD_VALUE, sf->captureLayers(args, captureResults));
+
+ TransactionUtils::fillSurfaceRGBA8(child, Color::RED);
+ SurfaceComposerClient::Transaction().apply(true);
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
+ ScreenCapture sc(captureResults.buffer);
+ sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+
+ sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
+ PIXEL_FORMAT_RGBA_8888, 0, child.get());
+
+ TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .setPosition(grandchild, 5, 5)
+ .show(grandchild)
+ .apply(true);
+
+ // Captures mFGSurfaceControl, its child, and the grandchild.
+ ScreenCapture::captureLayers(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+ mCapture->checkPixel(5, 5, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureChildOnly) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ auto childHandle = child->getHandle();
+
+ SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
+
+ // Captures only the child layer, and not the parent.
+ ScreenCapture::captureLayers(&mCapture, childHandle);
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+}
+
+TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
+ sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200);
+ auto childHandle = child->getHandle();
+
+ sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5,
+ PIXEL_FORMAT_RGBA_8888, 0, child.get());
+ TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .setPosition(grandchild, 5, 5)
+ .show(grandchild)
+ .apply(true);
+
+ auto grandchildHandle = grandchild->getHandle();
+
+ // Captures only the grandchild.
+ ScreenCapture::captureLayers(&mCapture, grandchildHandle);
+ mCapture->checkPixel(0, 0, 50, 50, 50);
+ mCapture->checkPixel(4, 4, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureCrop) {
+ sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+ sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
+ PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
+
+ SurfaceComposerClient::Transaction()
+ .setLayer(redLayer, INT32_MAX - 1)
+ .show(redLayer)
+ .show(blueLayer)
+ .apply(true);
+
+ auto redLayerHandle = redLayer->getHandle();
+
+ // Capturing full screen should have both red and blue are visible.
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+ const Rect crop = Rect(0, 0, 30, 30);
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
+ // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
+ // area visible.
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureSize) {
+ sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+ sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30,
+ PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
+
+ SurfaceComposerClient::Transaction()
+ .setLayer(redLayer, INT32_MAX - 1)
+ .show(redLayer)
+ .show(blueLayer)
+ .apply(true);
+
+ auto redLayerHandle = redLayer->getHandle();
+
+ // Capturing full screen should have both red and blue are visible.
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+ // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
+ mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
+ mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
+ sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0);
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+
+ auto redLayerHandle = redLayer->getHandle();
+ Transaction().reparent(redLayer, nullptr).apply();
+ redLayer.clear();
+ SurfaceComposerClient::Transaction().apply(true);
+
+ LayerCaptureArgs args;
+ args.layerHandle = redLayerHandle;
+
+ ScreenCaptureResults captureResults;
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
+ ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(args, captureResults));
+}
+
+// In the following tests we verify successful skipping of a parent layer,
+// so we use the same verification logic and only change how we mutate
+// the parent layer to verify that various properties are ignored.
+class ScreenCaptureChildOnlyTest : public ScreenCaptureTest {
+public:
+ void SetUp() override {
+ ScreenCaptureTest::SetUp();
+
+ mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0,
+ mFGSurfaceControl.get());
+ TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(mChild).apply(true);
+ }
+
+ void verify(std::function<void()> verifyStartingState) {
+ // Verify starting state before a screenshot is taken.
+ verifyStartingState();
+
+ // Verify child layer does not inherit any of the properties of its
+ // parent when its screenshot is captured.
+ auto fgHandle = mFGSurfaceControl->getHandle();
+ ScreenCapture::captureChildLayers(&mCapture, fgHandle);
+ mCapture->checkPixel(10, 10, 0, 0, 0);
+ mCapture->expectChildColor(0, 0);
+
+ // Verify all assumptions are still true after the screenshot is taken.
+ verifyStartingState();
+ }
+
+ std::unique_ptr<ScreenCapture> mCapture;
+ sp<SurfaceControl> mChild;
+};
+
+// Regression test b/76099859
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) {
+ SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true);
+
+ // Even though the parent is hidden we should still capture the child.
+
+ // Before and after reparenting, verify child is properly hidden
+ // when rendering full-screen.
+ verify([&] { screenshot()->expectBGColor(64, 64); });
+}
+
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) {
+ SurfaceComposerClient::Transaction()
+ .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1))
+ .apply(true);
+
+ // Even though the parent is cropped out we should still capture the child.
+
+ // Before and after reparenting, verify child is cropped by parent.
+ verify([&] { screenshot()->expectBGColor(65, 65); });
+}
+
+// Regression test b/124372894
+TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) {
+ SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true);
+
+ // We should not inherit the parent scaling.
+
+ // Before and after reparenting, verify child is properly scaled.
+ verify([&] { screenshot()->expectChildColor(80, 80); });
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index a03fd89..87fc08a 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -72,6 +72,9 @@
///////////////////////////////////////////////
+constexpr PhysicalDisplayId kPrimaryDisplayId = PhysicalDisplayId::fromPort(PRIMARY_DISPLAY);
+constexpr PhysicalDisplayId kExternalDisplayId = PhysicalDisplayId::fromPort(EXTERNAL_DISPLAY);
+
struct TestColor {
public:
uint8_t r;
@@ -272,6 +275,10 @@
mFakeComposerClient->runVSyncAndWait();
}
+ bool waitForHotplugEvent(Display displayId, bool connected) {
+ return waitForHotplugEvent(PhysicalDisplayId(displayId), connected);
+ }
+
bool waitForHotplugEvent(PhysicalDisplayId displayId, bool connected) {
int waitCount = 20;
while (waitCount--) {
@@ -280,9 +287,8 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
- "event hotplug: displayId %" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
- ", connected %d\t",
- event.header.displayId, event.hotplug.connected);
+ "event hotplug: displayId %s, connected %d\t",
+ to_string(event.header.displayId).c_str(), event.hotplug.connected);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
event.header.displayId == displayId && event.hotplug.connected == connected) {
@@ -295,7 +301,8 @@
return false;
}
- bool waitForConfigChangedEvent(PhysicalDisplayId displayId, int32_t configId) {
+ bool waitForConfigChangedEvent(Display display, int32_t configId) {
+ PhysicalDisplayId displayId(display);
int waitCount = 20;
while (waitCount--) {
while (!mReceivedDisplayEvents.empty()) {
@@ -303,9 +310,8 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED,
- "event config: displayId %" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
- ", configId %d\t",
- event.header.displayId, event.config.configId);
+ "event config: displayId %s, configId %d\t",
+ to_string(event.header.displayId).c_str(), event.config.configId);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
event.header.displayId == displayId && event.config.configId == configId) {
@@ -335,7 +341,7 @@
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
{
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
DisplayConfig config;
@@ -367,7 +373,7 @@
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
{
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_TRUE(display == nullptr);
DisplayConfig config;
@@ -396,7 +402,7 @@
waitForDisplayTransaction();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
DisplayConfig config;
@@ -503,7 +509,7 @@
waitForDisplayTransaction();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
DisplayConfig config;
@@ -619,7 +625,7 @@
waitForDisplayTransaction();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
DisplayConfig config;
@@ -808,7 +814,7 @@
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
{
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId);
EXPECT_TRUE(display == nullptr);
DisplayConfig config;
@@ -834,7 +840,7 @@
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
{
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId);
EXPECT_FALSE(display == nullptr);
DisplayConfig config;
@@ -988,7 +994,7 @@
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
ALOGI("TransactionTest::SetUp - display");
- const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId);
ASSERT_FALSE(display == nullptr);
DisplayConfig config;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 3c4a791..c46c914 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -40,7 +40,6 @@
"DispSyncSourceTest.cpp",
"DisplayIdentificationTest.cpp",
"DisplayTransactionTest.cpp",
- "EventControlThreadTest.cpp",
"EventThreadTest.cpp",
"HWComposerTest.cpp",
"OneShotTimerTest.cpp",
@@ -69,7 +68,6 @@
"mock/DisplayHardware/MockDisplay.cpp",
"mock/DisplayHardware/MockPowerAdvisor.cpp",
"mock/MockDispSync.cpp",
- "mock/MockEventControlThread.cpp",
"mock/MockEventThread.cpp",
"mock/MockMessageQueue.cpp",
"mock/MockNativeWindowSurface.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 9add6a5..48c4e18 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -42,7 +42,6 @@
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockDispSync.h"
-#include "mock/MockEventControlThread.h"
#include "mock/MockEventThread.h"
#include "mock/MockMessageQueue.h"
#include "mock/MockTimeStats.h"
@@ -81,7 +80,7 @@
constexpr hal::HWLayerId HWC_LAYER = 5000;
constexpr Transform DEFAULT_TRANSFORM = static_cast<Transform>(0);
-constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
+constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID(42);
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
@@ -150,11 +149,10 @@
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
+ constexpr ISchedulerCallback* kCallback = nullptr;
constexpr bool kHasMultipleConfigs = true;
- mFlinger.setupScheduler(std::move(primaryDispSync),
- std::make_unique<mock::EventControlThread>(),
- std::move(eventThread), std::move(sfEventThread),
- kHasMultipleConfigs);
+ mFlinger.setupScheduler(std::move(primaryDispSync), std::move(eventThread),
+ std::move(sfEventThread), kCallback, kHasMultipleConfigs);
// Layer history should be created if there are multiple configs.
ASSERT_TRUE(mFlinger.scheduler()->hasLayerHistory());
@@ -254,9 +252,8 @@
int fd = -1;
status_t result =
- mFlinger.captureScreenImplLocked(*renderArea, traverseLayers,
- mCaptureScreenBuffer.get(), useIdentityTransform,
- forSystem, &fd, regionSampling);
+ mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(),
+ useIdentityTransform, forSystem, &fd, regionSampling);
if (fd >= 0) {
close(fd);
}
@@ -897,7 +894,7 @@
static FlingerLayerType createLayer(CompositionTest* test) {
FlingerLayerType layer = Base::template createLayerWithFactory<EffectLayer>(test, [test]() {
return new EffectLayer(
- LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(), "test-layer",
+ LayerCreationArgs(test->mFlinger.flinger(), sp<Client>(), "test-layer",
LayerProperties::WIDTH, LayerProperties::HEIGHT,
LayerProperties::LAYER_FLAGS, LayerMetadata()));
});
@@ -936,8 +933,7 @@
FlingerLayerType layer =
Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
- sp<Client> client;
- LayerCreationArgs args(test->mFlinger.mFlinger.get(), client, "test-layer",
+ LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
LayerProperties::WIDTH, LayerProperties::HEIGHT,
LayerProperties::LAYER_FLAGS, LayerMetadata());
args.textureName = test->mFlinger.mutableTexturePool().back();
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index cc6a60c..02ce079 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -396,10 +396,10 @@
}
}
-TEST(DisplayIdentificationTest, getFallbackDisplayId) {
+TEST(DisplayIdentificationTest, fromPort) {
// Manufacturer ID should be invalid.
- ASSERT_FALSE(getPnpId(getFallbackDisplayId(0)));
- ASSERT_FALSE(getPnpId(getFallbackDisplayId(0xffu)));
+ ASSERT_FALSE(getPnpId(PhysicalDisplayId::fromPort(0)));
+ ASSERT_FALSE(getPnpId(PhysicalDisplayId::fromPort(0xffu)));
}
TEST(DisplayIdentificationTest, getVirtualDisplayId) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 9130b04..6086a05 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -46,10 +46,10 @@
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockDispSync.h"
-#include "mock/MockEventControlThread.h"
#include "mock/MockEventThread.h"
#include "mock/MockMessageQueue.h"
#include "mock/MockNativeWindowSurface.h"
+#include "mock/MockSchedulerCallback.h"
#include "mock/MockSurfaceInterceptor.h"
#include "mock/system/window/MockNativeWindow.h"
@@ -88,7 +88,7 @@
using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;
using HWC2Display = TestableSurfaceFlinger::HWC2Display;
-constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
constexpr int32_t DEFAULT_DPI = 320;
constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
@@ -156,7 +156,7 @@
mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
mock::DispSync* mPrimaryDispSync = new mock::DispSync;
- mock::EventControlThread* mEventControlThread = new mock::EventControlThread;
+ mock::SchedulerCallback mSchedulerCallback;
mock::EventThread* mEventThread = new mock::EventThread;
mock::EventThread* mSFEventThread = new mock::EventThread;
@@ -214,9 +214,8 @@
ISurfaceComposer::eConfigChangedSuppress)));
mFlinger.setupScheduler(std::unique_ptr<DispSync>(mPrimaryDispSync),
- std::unique_ptr<EventControlThread>(mEventControlThread),
std::unique_ptr<EventThread>(mEventThread),
- std::unique_ptr<EventThread>(mSFEventThread));
+ std::unique_ptr<EventThread>(mSFEventThread), &mSchedulerCallback);
}
void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) {
@@ -253,7 +252,7 @@
sp<DisplayDevice> DisplayTransactionTest::injectDefaultInternalDisplay(
std::function<void(FakeDisplayDeviceInjector&)> injectExtra) {
- constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777};
+ constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID(777);
constexpr int DEFAULT_DISPLAY_WIDTH = 1080;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1920;
constexpr HWDisplayId DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0;
@@ -332,10 +331,10 @@
*/
template <typename PhysicalDisplay>
-struct PhysicalDisplayId {};
+struct PhysicalDisplayIdType {};
-template <DisplayId::Type displayId>
-using VirtualDisplayId = std::integral_constant<DisplayId::Type, displayId>;
+template <uint64_t displayId>
+using VirtualDisplayIdType = std::integral_constant<uint64_t, displayId>;
struct NoDisplayId {};
@@ -343,18 +342,18 @@
struct IsPhysicalDisplayId : std::bool_constant<false> {};
template <typename PhysicalDisplay>
-struct IsPhysicalDisplayId<PhysicalDisplayId<PhysicalDisplay>> : std::bool_constant<true> {};
+struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {};
template <typename>
struct DisplayIdGetter;
template <typename PhysicalDisplay>
-struct DisplayIdGetter<PhysicalDisplayId<PhysicalDisplay>> {
- static std::optional<DisplayId> get() {
+struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
+ static std::optional<PhysicalDisplayId> get() {
if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
- return getFallbackDisplayId(static_cast<bool>(PhysicalDisplay::PRIMARY)
- ? LEGACY_DISPLAY_TYPE_PRIMARY
- : LEGACY_DISPLAY_TYPE_EXTERNAL);
+ return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
+ ? LEGACY_DISPLAY_TYPE_PRIMARY
+ : LEGACY_DISPLAY_TYPE_EXTERNAL);
}
const auto info =
@@ -364,9 +363,10 @@
}
};
-template <DisplayId::Type displayId>
-struct DisplayIdGetter<VirtualDisplayId<displayId>> {
- static std::optional<DisplayId> get() { return DisplayId{displayId}; }
+template <uint64_t displayId>
+struct DisplayIdGetter<VirtualDisplayIdType<displayId>> {
+ // TODO(b/160679868) Use VirtualDisplayId
+ static std::optional<PhysicalDisplayId> get() { return PhysicalDisplayId{displayId}; }
};
template <>
@@ -380,7 +380,7 @@
};
template <typename PhysicalDisplay>
-struct DisplayConnectionTypeGetter<PhysicalDisplayId<PhysicalDisplay>> {
+struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
};
@@ -391,19 +391,19 @@
constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
-template <DisplayId::Type displayId>
-struct HwcDisplayIdGetter<VirtualDisplayId<displayId>> {
+template <uint64_t displayId>
+struct HwcDisplayIdGetter<VirtualDisplayIdType<displayId>> {
static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
};
template <typename PhysicalDisplay>
-struct HwcDisplayIdGetter<PhysicalDisplayId<PhysicalDisplay>> {
+struct HwcDisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
};
// DisplayIdType can be:
-// 1) PhysicalDisplayId<...> for generated ID of physical display backed by HWC.
-// 2) VirtualDisplayId<...> for hard-coded ID of virtual display backed by HWC.
+// 1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC.
+// 2) VirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC.
// 3) NoDisplayId for virtual display without HWC backing.
template <typename DisplayIdType, int width, int height, Critical critical, Async async,
Secure secure, Primary primary, int grallocUsage>
@@ -631,10 +631,11 @@
template <typename PhysicalDisplay, int width, int height, Critical critical>
struct PhysicalDisplayVariant
- : DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height, critical, Async::FALSE,
- Secure::TRUE, PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
+ : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
+ Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
+ GRALLOC_USAGE_PHYSICAL_DISPLAY>,
HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
- DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height,
+ DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height,
critical, Async::FALSE, Secure::TRUE,
PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
PhysicalDisplay> {};
@@ -720,14 +721,14 @@
template <int width, int height, Secure secure>
struct HwcVirtualDisplayVariant
- : DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, secure,
- Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
- HwcDisplayVariant<
- HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
- DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE,
- secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
- using Base = DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE,
- secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>;
+ : DisplayVariant<VirtualDisplayIdType<42>, width, height, Critical::FALSE, Async::TRUE,
+ secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
+ HwcDisplayVariant<HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
+ DisplayVariant<VirtualDisplayIdType<42>, width, height, Critical::FALSE,
+ Async::TRUE, secure, Primary::FALSE,
+ GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
+ using Base = DisplayVariant<VirtualDisplayIdType<42>, width, height, Critical::FALSE,
+ Async::TRUE, secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>;
using Self = HwcVirtualDisplayVariant<width, height, secure>;
static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
@@ -1322,7 +1323,7 @@
// Call Expectations
// The call disable vsyncs
- EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1);
+ EXPECT_CALL(mSchedulerCallback, setVsyncEnabled(false)).Times(1);
// The call ends any display resyncs
EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1);
@@ -1522,7 +1523,6 @@
mHardwareDisplaySize.height),
compositionState.transform);
EXPECT_EQ(TRANSFORM_FLAGS_ROT_0, compositionState.orientation);
- EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.sourceClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.frame);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.viewport);
@@ -1535,7 +1535,6 @@
mHardwareDisplaySize.height),
compositionState.transform);
EXPECT_EQ(TRANSFORM_FLAGS_ROT_90, compositionState.orientation);
- EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.sourceClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
// For 90, the frame and viewport have the hardware display size width and height swapped
EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.frame);
@@ -1549,8 +1548,6 @@
mHardwareDisplaySize.height),
compositionState.transform);
EXPECT_EQ(TRANSFORM_FLAGS_ROT_180, compositionState.orientation);
- EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.sourceClip);
- EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.frame);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.viewport);
EXPECT_EQ(false, compositionState.needsFiltering);
@@ -1562,7 +1559,6 @@
mHardwareDisplaySize.height),
compositionState.transform);
EXPECT_EQ(TRANSFORM_FLAGS_ROT_270, compositionState.orientation);
- EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.sourceClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
// For 270, the frame and viewport have the hardware display size width and height swapped
EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.frame);
@@ -1821,7 +1817,9 @@
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
- state.physical = {.id = *displayId, .type = *connectionType, .hwcDisplayId = *hwcDisplayId};
+ state.physical = {.id = static_cast<PhysicalDisplayId>(*displayId),
+ .type = *connectionType,
+ .hwcDisplayId = *hwcDisplayId};
}
state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -1997,7 +1995,7 @@
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
- expectedPhysical = {.id = *displayId,
+ expectedPhysical = {.id = static_cast<PhysicalDisplayId>(*displayId),
.type = *connectionType,
.hwcDisplayId = *hwcDisplayId};
}
@@ -3212,9 +3210,9 @@
};
struct EventThreadBaseSupportedVariant {
- static void setupEventAndEventControlThreadNoCallExpectations(DisplayTransactionTest* test) {
- // The event control thread should not be notified.
- EXPECT_CALL(*test->mEventControlThread, setVsyncEnabled(_)).Times(0);
+ static void setupVsyncAndEventThreadNoCallExpectations(DisplayTransactionTest* test) {
+ // The callback should not be notified to toggle VSYNC.
+ EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(_)).Times(0);
// The event thread should not be notified.
EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(0);
@@ -3227,29 +3225,29 @@
// These calls are only expected for the primary display.
// Instead expect no calls.
- setupEventAndEventControlThreadNoCallExpectations(test);
+ setupVsyncAndEventThreadNoCallExpectations(test);
}
static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
// These calls are only expected for the primary display.
// Instead expect no calls.
- setupEventAndEventControlThreadNoCallExpectations(test);
+ setupVsyncAndEventThreadNoCallExpectations(test);
}
};
struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant {
static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
- // The event control thread should be notified to enable vsyncs
- EXPECT_CALL(*test->mEventControlThread, setVsyncEnabled(true)).Times(1);
+ // The callback should be notified to enable VSYNC.
+ EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(true)).Times(1);
// The event thread should be notified that the screen was acquired.
EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(1);
}
static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
- // There should be a call to setVsyncEnabled(false)
- EXPECT_CALL(*test->mEventControlThread, setVsyncEnabled(false)).Times(1);
+ // The callback should be notified to disable VSYNC.
+ EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(false)).Times(1);
// The event thread should not be notified that the screen was released.
EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(1);
@@ -3308,7 +3306,7 @@
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
- Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
+ Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
Case::setupRepaintEverythingCallExpectations(test);
}
@@ -3335,7 +3333,7 @@
: public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
+ Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
}
@@ -3347,7 +3345,7 @@
struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
+ Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
}
};
@@ -3365,7 +3363,7 @@
struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
+ Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
}
};
@@ -3394,7 +3392,7 @@
: public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
- Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
+ Case::EventThread::setupVsyncAndEventThreadNoCallExpectations(test);
Case::setupNoComposerPowerModeCallExpectations(test);
}
};
diff --git a/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp
deleted file mode 100644
index 9dc4193..0000000
--- a/services/surfaceflinger/tests/unittests/EventControlThreadTest.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "LibSurfaceFlingerUnittests"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <log/log.h>
-
-#include "AsyncCallRecorder.h"
-#include "Scheduler/EventControlThread.h"
-
-namespace android {
-namespace {
-
-using namespace std::chrono_literals;
-using testing::_;
-
-class EventControlThreadTest : public testing::Test {
-protected:
- EventControlThreadTest();
- ~EventControlThreadTest() override;
-
- void createThread();
-
- void expectVSyncEnableCallbackCalled(bool enable);
-
- AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
-
- std::unique_ptr<EventControlThread> mThread;
-};
-
-EventControlThreadTest::EventControlThreadTest() {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-}
-
-EventControlThreadTest::~EventControlThreadTest() {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
-}
-
-void EventControlThreadTest::createThread() {
- mThread = std::make_unique<android::impl::EventControlThread>(
- mVSyncSetEnabledCallRecorder.getInvocable());
-}
-
-void EventControlThreadTest::expectVSyncEnableCallbackCalled(bool expectedEnabled) {
- auto args = mVSyncSetEnabledCallRecorder.waitForCall();
- ASSERT_TRUE(args.has_value());
- EXPECT_EQ(std::get<0>(args.value()), expectedEnabled);
-}
-
-/* ------------------------------------------------------------------------
- * Test cases
- */
-
-TEST_F(EventControlThreadTest, signalsVSyncDisabledOnStartup) {
- createThread();
-
- // On thread start, there should be an automatic explicit call to disable
- // vsyncs
- expectVSyncEnableCallbackCalled(false);
-}
-
-TEST_F(EventControlThreadTest, signalsVSyncDisabledOnce) {
- createThread();
- expectVSyncEnableCallbackCalled(false);
-
- mThread->setVsyncEnabled(false);
-
- EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
-}
-
-TEST_F(EventControlThreadTest, signalsVSyncEnabledThenDisabled) {
- createThread();
- expectVSyncEnableCallbackCalled(false);
-
- mThread->setVsyncEnabled(true);
-
- expectVSyncEnableCallbackCalled(true);
-
- mThread->setVsyncEnabled(false);
-
- expectVSyncEnableCallbackCalled(false);
-}
-
-TEST_F(EventControlThreadTest, signalsVSyncEnabledOnce) {
- createThread();
- expectVSyncEnableCallbackCalled(false);
-
- mThread->setVsyncEnabled(true);
-
- expectVSyncEnableCallbackCalled(true);
-
- mThread->setVsyncEnabled(true);
-
- EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
-}
-
-} // namespace
-} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index b90b566..aab6d01 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -36,9 +36,9 @@
namespace {
-constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = 111;
-constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID = 222;
-constexpr PhysicalDisplayId DISPLAY_ID_64BIT = 0xabcd12349876fedcULL;
+constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID(111);
+constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID(222);
+constexpr PhysicalDisplayId DISPLAY_ID_64BIT(0xabcd12349876fedcULL);
class MockVSyncSource : public VSyncSource {
public:
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 91b304c..fa12315 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -23,7 +23,13 @@
#include <vector>
+// StrictMock<T> derives from T and is not marked final, so the destructor of T is expected to be
+// virtual in case StrictMock<T> is used as a polymorphic base class. That is not the case here.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#include <gmock/gmock.h>
+#pragma clang diagnostic pop
+
#include <gui/LayerMetadata.h>
#include <log/log.h>
@@ -45,27 +51,20 @@
using ::testing::SetArgPointee;
using ::testing::StrictMock;
-struct MockHWC2ComposerCallback : public HWC2::ComposerCallback {
- ~MockHWC2ComposerCallback() = default;
-
- MOCK_METHOD3(onHotplugReceived,
- void(int32_t sequenceId, hal::HWDisplayId display, hal::Connection connection));
- MOCK_METHOD2(onRefreshReceived, void(int32_t sequenceId, hal::HWDisplayId display));
+struct MockHWC2ComposerCallback final : StrictMock<HWC2::ComposerCallback> {
+ MOCK_METHOD3(onHotplugReceived, void(int32_t sequenceId, hal::HWDisplayId, hal::Connection));
+ MOCK_METHOD2(onRefreshReceived, void(int32_t sequenceId, hal::HWDisplayId));
MOCK_METHOD4(onVsyncReceived,
- void(int32_t sequenceId, hal::HWDisplayId display, int64_t timestamp,
- std::optional<hal::VsyncPeriodNanos> vsyncPeriod));
+ void(int32_t sequenceId, hal::HWDisplayId, int64_t timestamp,
+ std::optional<hal::VsyncPeriodNanos>));
MOCK_METHOD3(onVsyncPeriodTimingChangedReceived,
- void(int32_t sequenceId, hal::HWDisplayId display,
- const hal::VsyncPeriodChangeTimeline& updatedTimeline));
- MOCK_METHOD2(onSeamlessPossible, void(int32_t sequenceId, hal::HWDisplayId display));
+ void(int32_t sequenceId, hal::HWDisplayId, const hal::VsyncPeriodChangeTimeline&));
+ MOCK_METHOD2(onSeamlessPossible, void(int32_t sequenceId, hal::HWDisplayId));
};
-struct HWComposerTest : public testing::Test {
+struct HWComposerSetConfigurationTest : testing::Test {
Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
-};
-
-struct HWComposerSetConfigurationTest : public HWComposerTest {
- StrictMock<MockHWC2ComposerCallback> mCallback;
+ MockHWC2ComposerCallback mCallback;
};
TEST_F(HWComposerSetConfigurationTest, loadsLayerMetadataSupport) {
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 3ab22d3..0fbe8ec 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -30,6 +30,7 @@
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/MockLayer.h"
+#include "mock/MockSchedulerCallback.h"
using testing::_;
using testing::Return;
@@ -75,7 +76,13 @@
.setConfigGroup(0)
.build()},
HwcConfigIndexType(0)};
- TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, false)};
+
+ mock::NoOpSchedulerCallback mSchedulerCallback;
+ static constexpr bool kUseContentDetectionV2 = false;
+
+ TestableScheduler* const mScheduler =
+ new TestableScheduler(mConfigs, mSchedulerCallback, kUseContentDetectionV2);
+
TestableSurfaceFlinger mFlinger;
const nsecs_t mTime = systemTime();
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 1705835..cb376cd 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -27,6 +27,7 @@
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/MockLayer.h"
+#include "mock/MockSchedulerCallback.h"
using testing::_;
using testing::Return;
@@ -115,9 +116,14 @@
.setConfigGroup(0)
.build()},
HwcConfigIndexType(0)};
- TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, true)};
- TestableSurfaceFlinger mFlinger;
+ mock::NoOpSchedulerCallback mSchedulerCallback;
+ static constexpr bool kUseContentDetectionV2 = true;
+
+ TestableScheduler* const mScheduler =
+ new TestableScheduler(mConfigs, mSchedulerCallback, kUseContentDetectionV2);
+
+ TestableSurfaceFlinger mFlinger;
};
namespace {
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index 43b8e01..f6bf05a 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -32,7 +32,6 @@
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDispSync.h"
-#include "mock/MockEventControlThread.h"
#include "mock/MockEventThread.h"
namespace android {
@@ -146,8 +145,7 @@
EXPECT_CALL(*primaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
- mFlinger.setupScheduler(std::move(primaryDispSync),
- std::make_unique<mock::EventControlThread>(), std::move(eventThread),
+ mFlinger.setupScheduler(std::move(primaryDispSync), std::move(eventThread),
std::move(sfEventThread));
}
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 382199d..39e793a 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -14,20 +14,12 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#undef LOG_TAG
-#define LOG_TAG "SchedulerUnittests"
-
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <mutex>
-#include "Scheduler/EventControlThread.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateConfigs.h"
#include "TestableScheduler.h"
@@ -35,13 +27,15 @@
#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockEventThread.h"
#include "mock/MockLayer.h"
+#include "mock/MockSchedulerCallback.h"
using testing::_;
using testing::Return;
namespace android {
+namespace {
-constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID = 999;
+constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID(999);
class SchedulerTest : public testing::Test {
protected:
@@ -58,7 +52,6 @@
};
SchedulerTest();
- ~SchedulerTest() override;
Hwc2::mock::Display mDisplay;
const scheduler::RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0)
@@ -67,7 +60,17 @@
.build()},
HwcConfigIndexType(0)};
- TestableScheduler mScheduler{mConfigs, false};
+ mock::SchedulerCallback mSchedulerCallback;
+
+ // The scheduler should initially disable VSYNC.
+ struct ExpectDisableVsync {
+ ExpectDisableVsync(mock::SchedulerCallback& callback) {
+ EXPECT_CALL(callback, setVsyncEnabled(false)).Times(1);
+ }
+ } mExpectDisableVsync{mSchedulerCallback};
+
+ static constexpr bool kUseContentDetectionV2 = false;
+ TestableScheduler mScheduler{mConfigs, mSchedulerCallback, kUseContentDetectionV2};
Scheduler::ConnectionHandle mConnectionHandle;
mock::EventThread* mEventThread;
@@ -75,10 +78,6 @@
};
SchedulerTest::SchedulerTest() {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-
auto eventThread = std::make_unique<mock::EventThread>();
mEventThread = eventThread.get();
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
@@ -94,15 +93,7 @@
EXPECT_TRUE(mConnectionHandle);
}
-SchedulerTest::~SchedulerTest() {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
-}
-
-/* ------------------------------------------------------------------------
- * Test cases
- */
+} // namespace
TEST_F(SchedulerTest, invalidConnectionHandle) {
Scheduler::ConnectionHandle handle;
@@ -159,8 +150,7 @@
mScheduler.setPhaseOffset(mConnectionHandle, 10);
static constexpr size_t kEventConnections = 5;
- ON_CALL(*mEventThread, getEventThreadConnectionCount())
- .WillByDefault(Return(kEventConnections));
+ EXPECT_CALL(*mEventThread, getEventThreadConnectionCount()).WillOnce(Return(kEventConnections));
EXPECT_EQ(kEventConnections, mScheduler.getEventThreadConnectionCount(mConnectionHandle));
}
@@ -181,11 +171,8 @@
constexpr uint32_t kDisplayArea = 999'999;
mScheduler.onPrimaryDisplayAreaChanged(kDisplayArea);
+ EXPECT_CALL(mSchedulerCallback, changeRefreshRate(_, _)).Times(0);
mScheduler.chooseRefreshRateForContent();
- EXPECT_EQ(0, mScheduler.refreshRateChangeCount());
}
} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 0d6c799..6c01f85 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -33,7 +33,6 @@
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDispSync.h"
-#include "mock/MockEventControlThread.h"
#include "mock/MockEventThread.h"
#include "mock/MockMessageQueue.h"
@@ -182,8 +181,7 @@
EXPECT_CALL(*primaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
- mFlinger.setupScheduler(std::move(primaryDispSync),
- std::make_unique<mock::EventControlThread>(), std::move(eventThread),
+ mFlinger.setupScheduler(std::move(primaryDispSync), std::move(eventThread),
std::move(sfEventThread));
}
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index c463294..d78546d 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -23,20 +23,27 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/Scheduler.h"
+#include "Scheduler/VSyncTracker.h"
+#include "mock/MockDispSync.h"
namespace android {
-class TestableScheduler : public Scheduler, private ISchedulerCallback {
+class TestableScheduler : public Scheduler {
public:
- TestableScheduler(const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2)
- : Scheduler([](bool) {}, configs, *this, useContentDetectionV2, true) {}
+ TestableScheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
+ bool useContentDetectionV2)
+ : TestableScheduler(std::make_unique<mock::DispSync>(), configs, callback,
+ useContentDetectionV2) {}
TestableScheduler(std::unique_ptr<DispSync> primaryDispSync,
- std::unique_ptr<EventControlThread> eventControlThread,
- const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2)
- : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this,
- createLayerHistory(configs, useContentDetectionV2), useContentDetectionV2,
- true) {}
+ const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
+ bool useContentDetectionV2)
+ : Scheduler({std::move(primaryDispSync), nullptr, nullptr}, configs, callback,
+ createLayerHistory(configs, useContentDetectionV2),
+ {.supportKernelTimer = false,
+ .useContentDetection = true,
+ .useContentDetectionV2 = useContentDetectionV2,
+ .useVsyncPredictor = false}) {}
// Used to inject mock event thread.
ConnectionHandle createConnection(std::unique_ptr<EventThread> eventThread) {
@@ -48,28 +55,24 @@
* post-conditions.
*/
auto& mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
- auto& mutableEventControlThread() { return mEventControlThread; }
- auto& mutablePrimaryDispSync() { return mPrimaryDispSync; }
auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
- size_t refreshRateChangeCount() const { return mRefreshRateChangeCount; }
-
bool hasLayerHistory() const { return static_cast<bool>(mLayerHistory); }
auto* mutableLayerHistory() {
- LOG_ALWAYS_FATAL_IF(mUseContentDetectionV2);
+ LOG_ALWAYS_FATAL_IF(mOptions.useContentDetectionV2);
return static_cast<scheduler::impl::LayerHistory*>(mLayerHistory.get());
}
auto* mutableLayerHistoryV2() {
- LOG_ALWAYS_FATAL_IF(!mUseContentDetectionV2);
+ LOG_ALWAYS_FATAL_IF(!mOptions.useContentDetectionV2);
return static_cast<scheduler::impl::LayerHistoryV2*>(mLayerHistory.get());
}
size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
if (!mLayerHistory) return 0;
- return mUseContentDetectionV2 ? mutableLayerHistoryV2()->mLayerInfos.size()
- : mutableLayerHistory()->mLayerInfos.size();
+ return mOptions.useContentDetectionV2 ? mutableLayerHistoryV2()->mLayerInfos.size()
+ : mutableLayerHistory()->mLayerInfos.size();
}
void replaceTouchTimer(int64_t millis) {
@@ -93,18 +96,9 @@
// not report a leaked object, since the Scheduler instance may
// still be referenced by something despite our best efforts to destroy
// it after each test is done.
- mutableEventControlThread().reset();
- mutablePrimaryDispSync().reset();
+ mVsyncSchedule.sync.reset();
mConnections.clear();
}
-
-private:
- void changeRefreshRate(const RefreshRate&, ConfigEvent) override { mRefreshRateChangeCount++; }
-
- void repaintEverythingForHWC() override {}
- void kernelTimerChanged(bool /*expired*/) override {}
-
- size_t mRefreshRateChangeCount = 0;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 256e048..3941d42 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -69,11 +69,6 @@
return nullptr;
}
- std::unique_ptr<EventControlThread> createEventControlThread(
- std::function<void(bool)>) override {
- return nullptr;
- }
-
std::unique_ptr<HWComposer> createHWComposer(const std::string&) override {
return nullptr;
}
@@ -87,8 +82,7 @@
return std::make_unique<scheduler::FakePhaseOffsets>();
}
- std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>,
- const scheduler::RefreshRateConfigs&,
+ std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&,
ISchedulerCallback&) override {
return nullptr;
}
@@ -175,7 +169,7 @@
} // namespace surfaceflinger::test
-class TestableSurfaceFlinger {
+class TestableSurfaceFlinger final : private ISchedulerCallback {
public:
using HotplugEvent = SurfaceFlinger::HotplugEvent;
@@ -198,11 +192,11 @@
mFlinger->mCompositionEngine->setTimeStats(timeStats);
}
+ // The ISchedulerCallback argument can be nullptr for a no-op implementation.
void setupScheduler(std::unique_ptr<DispSync> primaryDispSync,
- std::unique_ptr<EventControlThread> eventControlThread,
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
- bool hasMultipleConfigs = false) {
+ ISchedulerCallback* callback = nullptr, bool hasMultipleConfigs = false) {
std::vector<std::shared_ptr<const HWC2::Display::Config>> configs{
HWC2::Display::Config::Builder(mDisplay, 0)
.setVsyncPeriod(16'666'667)
@@ -227,8 +221,8 @@
constexpr bool kUseContentDetectionV2 = false;
mScheduler =
- new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread),
- *mFlinger->mRefreshRateConfigs, kUseContentDetectionV2);
+ new TestableScheduler(std::move(primaryDispSync), *mFlinger->mRefreshRateConfigs,
+ *(callback ?: this), kUseContentDetectionV2);
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
@@ -339,14 +333,14 @@
auto onMessageReceived(int32_t what) { return mFlinger->onMessageReceived(what, systemTime()); }
- auto captureScreenImplLocked(const RenderArea& renderArea,
- SurfaceFlinger::TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
- bool forSystem, int* outSyncFd, bool regionSampling) {
- bool ignored;
- return mFlinger->captureScreenImplLocked(renderArea, traverseLayers, buffer,
- useIdentityTransform, forSystem, outSyncFd,
- regionSampling, ignored);
+ auto renderScreenImplLocked(const RenderArea& renderArea,
+ SurfaceFlinger::TraverseLayersFunction traverseLayers,
+ const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
+ bool forSystem, int* outSyncFd, bool regionSampling) {
+ ScreenCaptureResults captureResults;
+ return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer,
+ useIdentityTransform, forSystem, outSyncFd,
+ regionSampling, captureResults);
}
auto traverseLayersInLayerStack(ui::LayerStack layerStack,
@@ -643,7 +637,9 @@
if (const auto type = mCreationArgs.connectionType) {
LOG_ALWAYS_FATAL_IF(!displayId);
LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
- state.physical = {.id = *displayId, .type = *type, .hwcDisplayId = *mHwcDisplayId};
+ state.physical = {.id = static_cast<PhysicalDisplayId>(*displayId),
+ .type = *type,
+ .hwcDisplayId = *mHwcDisplayId};
}
state.isSecure = mCreationArgs.isSecure;
@@ -667,6 +663,12 @@
const std::optional<hal::HWDisplayId> mHwcDisplayId;
};
+private:
+ void setVsyncEnabled(bool) override {}
+ void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override {}
+ void repaintEverythingForHWC() override {}
+ void kernelTimerChanged(bool) override {}
+
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
TestableScheduler* mScheduler = nullptr;
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index 63a34af..0a24650 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -221,7 +221,7 @@
}
static std::string genLayerName(int32_t layerId) {
- return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerId);
+ return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.example.fake#") + std::to_string(layerId);
}
void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
@@ -424,7 +424,7 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(8ms)
.count());
- // Push a dummy present fence to trigger flushing the RenderEngine timings.
+ // Push a fake present fence to trigger flushing the RenderEngine timings.
mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(
std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count()));
@@ -505,7 +505,7 @@
ASSERT_TRUE(preFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
- // Push a dummy present fence to trigger flushing the RenderEngine timings.
+ // Push a fake present fence to trigger flushing the RenderEngine timings.
mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(
std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count()));
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 2a48a22..44b3dc0 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -32,7 +32,6 @@
#include "TestableScheduler.h"
#include "TestableSurfaceFlinger.h"
#include "mock/MockDispSync.h"
-#include "mock/MockEventControlThread.h"
#include "mock/MockEventThread.h"
#include "mock/MockMessageQueue.h"
@@ -81,7 +80,6 @@
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
mFlinger.setupScheduler(std::unique_ptr<mock::DispSync>(mPrimaryDispSync),
- std::make_unique<mock::EventControlThread>(),
std::move(eventThread), std::move(sfEventThread));
}
@@ -89,7 +87,6 @@
TestableSurfaceFlinger mFlinger;
std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>();
- mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
mock::DispSync* mPrimaryDispSync = new mock::DispSync();
diff --git a/services/surfaceflinger/tests/unittests/VSyncModulatorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncModulatorTest.cpp
index 9c1ec07..af1e84b 100644
--- a/services/surfaceflinger/tests/unittests/VSyncModulatorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncModulatorTest.cpp
@@ -27,15 +27,15 @@
namespace android::scheduler {
-class MockScheduler : public IPhaseOffsetControl {
+class MockScheduler final : public IPhaseOffsetControl {
public:
- void setPhaseOffset(ConnectionHandle handle, nsecs_t phaseOffset) {
- mPhaseOffset[handle] = phaseOffset;
- }
-
nsecs_t getOffset(ConnectionHandle handle) { return mPhaseOffset[handle]; }
private:
+ void setPhaseOffset(ConnectionHandle handle, nsecs_t phaseOffset) override {
+ mPhaseOffset[handle] = phaseOffset;
+ }
+
std::unordered_map<ConnectionHandle, nsecs_t> mPhaseOffset;
};
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.cpp b/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.cpp
deleted file mode 100644
index f9bacc8..0000000
--- a/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2018 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 "mock/MockEventControlThread.h"
-
-namespace android {
-namespace mock {
-
-// Explicit default instantiation is recommended.
-EventControlThread::EventControlThread() = default;
-EventControlThread::~EventControlThread() = default;
-
-} // namespace mock
-} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h
deleted file mode 100644
index 6ef352a..0000000
--- a/services/surfaceflinger/tests/unittests/mock/MockEventControlThread.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <gmock/gmock.h>
-
-#include "Scheduler/EventControlThread.h"
-
-namespace android {
-namespace mock {
-
-class EventControlThread : public android::EventControlThread {
-public:
- EventControlThread();
- ~EventControlThread() override;
-
- MOCK_METHOD1(setVsyncEnabled, void(bool));
-};
-
-} // namespace mock
-} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
new file mode 100644
index 0000000..72bc89c
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "Scheduler/Scheduler.h"
+
+namespace android::mock {
+
+struct SchedulerCallback final : ISchedulerCallback {
+ MOCK_METHOD1(setVsyncEnabled, void(bool));
+ MOCK_METHOD2(changeRefreshRate,
+ void(const scheduler::RefreshRateConfigs::RefreshRate&,
+ scheduler::RefreshRateConfigEvent));
+ MOCK_METHOD0(repaintEverythingForHWC, void());
+ MOCK_METHOD1(kernelTimerChanged, void(bool));
+};
+
+struct NoOpSchedulerCallback final : ISchedulerCallback {
+ void setVsyncEnabled(bool) override {}
+ void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
+ scheduler::RefreshRateConfigEvent) override {}
+ void repaintEverythingForHWC() override {}
+ void kernelTimerChanged(bool) override {}
+};
+
+} // namespace android::mock
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index 5480b00..d73506b 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -35,9 +35,12 @@
const auto sf = ComposerService::getComposerService();
SurfaceComposerClient::Transaction().apply(true);
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR, sf->captureScreen(displayToken, &outBuffer, Rect(), 0, 0, false));
- *sc = std::make_unique<ScreenCapture>(outBuffer);
+ DisplayCaptureArgs args;
+ args.displayToken = displayToken;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(NO_ERROR, sf->captureDisplay(args, captureResults));
+ *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
}
static void captureLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
@@ -45,9 +48,15 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
SurfaceComposerClient::Transaction().apply(true);
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale));
- *sc = std::make_unique<ScreenCapture>(outBuffer);
+ LayerCaptureArgs args;
+ args.layerHandle = parentHandle;
+ args.sourceCrop = crop;
+ args.frameScale = frameScale;
+ args.childrenOnly = false;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
+ *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
}
static void captureChildLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
@@ -55,9 +64,15 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
SurfaceComposerClient::Transaction().apply(true);
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale, true));
- *sc = std::make_unique<ScreenCapture>(outBuffer);
+ LayerCaptureArgs args;
+ args.layerHandle = parentHandle;
+ args.sourceCrop = crop;
+ args.frameScale = frameScale;
+ args.childrenOnly = true;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
+ *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
}
static void captureChildLayersExcluding(
@@ -66,12 +81,17 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
SurfaceComposerClient::Transaction().apply(true);
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR,
- sf->captureLayers(parentHandle, &outBuffer, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888, Rect::EMPTY_RECT, excludeLayers,
- 1.0f, true));
- *sc = std::make_unique<ScreenCapture>(outBuffer);
+ LayerCaptureArgs args;
+ args.layerHandle = parentHandle;
+ args.pixelFormat = ui::PixelFormat::RGBA_8888;
+ args.sourceCrop = Rect::EMPTY_RECT;
+ args.excludeHandles = excludeLayers;
+ args.frameScale = 1.0f;
+ args.childrenOnly = true;
+
+ ScreenCaptureResults captureResults;
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(args, captureResults));
+ *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
}
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
diff --git a/services/vibratorservice/TEST_MAPPING b/services/vibratorservice/TEST_MAPPING
new file mode 100644
index 0000000..b033adb
--- /dev/null
+++ b/services/vibratorservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libvibratorservice_test"
+ }
+ ]
+}
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index 9ffe83b..ba98696 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -27,17 +27,19 @@
#define VK_ANDROID_native_buffer 1
#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 11
-/* NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 6
+/*
+ * NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 6
*
* This version of the extension transitions from gralloc0 to gralloc1 usage
* flags (int -> 2x uint64_t). The WSI implementation will temporarily continue
* to fill out deprecated fields in VkNativeBufferANDROID, and will call the
* deprecated vkGetSwapchainGrallocUsageANDROID if the new
* vkGetSwapchainGrallocUsage2ANDROID is not supported. This transitionary
- * backwards-compatibility support is temporary, and will likely be removed in
+ * backwards-compatibility support is temporary, and will likely be removed
* (along with all gralloc0 support) in a future release.
*/
-/* NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 8
+/*
+ * NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 8
*
* This version of the extension doesn't introduce new types or structs, but is
* to accommodate the new struct VkBindImageMemorySwapchainInfoKHR added in
@@ -47,97 +49,155 @@
* in VkBindImageMemorySwapchainInfoKHR will be additionally chained to the
* pNext chain of VkBindImageMemoryInfo and passed down to the driver.
*/
-#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 8
-#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME "VK_ANDROID_native_buffer"
+#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 8
+#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME "VK_ANDROID_native_buffer"
-#define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id) ((type)(1000000000 + (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
-#define VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 0)
-#define VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 1)
-#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 2)
+#define VK_ANDROID_NATIVE_BUFFER_ENUM(type, id) \
+ ((type)(1000000000 + \
+ (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
+#define VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID \
+ VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 0)
+#define VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID \
+ VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 1)
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID \
+ VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 2)
+/* clang-format off */
typedef enum VkSwapchainImageUsageFlagBitsANDROID {
VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0x00000001,
VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSwapchainImageUsageFlagBitsANDROID;
typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
+/*
+ * struct VkNativeBufferUsage2ANDROID
+ *
+ * consumer: gralloc1 consumer usage flag
+ * producer: gralloc1 producer usage flag
+ */
typedef struct {
- uint64_t consumer;
- uint64_t producer;
+ uint64_t consumer;
+ uint64_t producer;
} VkNativeBufferUsage2ANDROID;
+/*
+ * struct VkNativeBufferANDROID
+ *
+ * sType: VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
+ * pNext: NULL or a pointer to a structure extending this structure
+ * handle: buffer handle returned from gralloc alloc()
+ * stride: stride returned from gralloc alloc()
+ * format: gralloc format requested when the buffer was allocated
+ * usage: gralloc usage requested when the buffer was allocated
+ * usage2: gralloc usage requested when the buffer was allocated
+ */
typedef struct {
- VkStructureType sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
- const void* pNext;
-
- // Buffer handle and stride returned from gralloc alloc()
- buffer_handle_t handle;
- int stride;
-
- // Gralloc format and usage requested when the buffer was allocated.
- int format;
- int usage; // DEPRECATED in SPEC_VERSION 6
- // -- Added in SPEC_VERSION 6 --
- VkNativeBufferUsage2ANDROID usage2;
+ VkStructureType sType;
+ const void* pNext;
+ buffer_handle_t handle;
+ int stride;
+ int format;
+ int usage; /* DEPRECATED in SPEC_VERSION 6 */
+ VkNativeBufferUsage2ANDROID usage2; /* ADDED in SPEC_VERSION 6 */
} VkNativeBufferANDROID;
+/*
+ * struct VkSwapchainImageCreateInfoANDROID
+ *
+ * sType: VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
+ * pNext: NULL or a pointer to a structure extending this structure
+ * usage: is a bitmask of VkSwapchainImageUsageFlagsANDROID
+ */
typedef struct {
- VkStructureType sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
- const void* pNext;
-
- VkSwapchainImageUsageFlagsANDROID usage;
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainImageUsageFlagsANDROID usage;
} VkSwapchainImageCreateInfoANDROID;
+/*
+ * struct VkPhysicalDevicePresentationPropertiesANDROID
+ *
+ * sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID
+ * pNext: NULL or a pointer to a structure extending this structure
+ * sharedImage: specifies if the image can be shared with the display system
+ */
typedef struct {
- VkStructureType sType; // must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID
- const void* pNext;
-
- VkBool32 sharedImage;
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 sharedImage;
} VkPhysicalDevicePresentationPropertiesANDROID;
-// -- DEPRECATED in SPEC_VERSION 6 --
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-// -- ADDED in SPEC_VERSION 6 --
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
-typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
+/* DEPRECATED in SPEC_VERSION 6 */
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int* grallocUsage);
+
+/* ADDED in SPEC_VERSION 6 */
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+ uint64_t* grallocConsumerUsage,
+ uint64_t* grallocProducerUsage);
+
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(
+ VkDevice device,
+ VkImage image,
+ int nativeFenceFd,
+ VkSemaphore semaphore,
+ VkFence fence);
+
+typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(
+ VkQueue queue,
+ uint32_t waitSemaphoreCount,
+ const VkSemaphore* pWaitSemaphores,
+ VkImage image,
+ int* pNativeFenceFd);
#ifndef VK_NO_PROTOTYPES
-// -- DEPRECATED in SPEC_VERSION 6 --
+/* DEPRECATED in SPEC_VERSION 6 */
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsageANDROID(
- VkDevice device,
- VkFormat format,
- VkImageUsageFlags imageUsage,
- int* grallocUsage
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int* grallocUsage
);
-// -- ADDED in SPEC_VERSION 6 --
+
+/* ADDED in SPEC_VERSION 6 */
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(
- VkDevice device,
- VkFormat format,
- VkImageUsageFlags imageUsage,
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
- uint64_t* grallocConsumerUsage,
- uint64_t* grallocProducerUsage
+ uint64_t* grallocConsumerUsage,
+ uint64_t* grallocProducerUsage
);
+
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID(
- VkDevice device,
- VkImage image,
- int nativeFenceFd,
- VkSemaphore semaphore,
- VkFence fence
+ VkDevice device,
+ VkImage image,
+ int nativeFenceFd,
+ VkSemaphore semaphore,
+ VkFence fence
);
+
VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(
- VkQueue queue,
- uint32_t waitSemaphoreCount,
- const VkSemaphore* pWaitSemaphores,
- VkImage image,
- int* pNativeFenceFd
+ VkQueue queue,
+ uint32_t waitSemaphoreCount,
+ const VkSemaphore* pWaitSemaphores,
+ VkImage image,
+ int* pNativeFenceFd
);
+
#endif
+/* clang-format on */
#ifdef __cplusplus
}
#endif
-#endif // __VK_ANDROID_NATIVE_BUFFER_H__
+#endif /* __VK_ANDROID_NATIVE_BUFFER_H__ */