diff options
93 files changed, 2014 insertions, 850 deletions
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc index c7c3a34521..006e5329cd 100644 --- a/cmds/atrace/atrace.rc +++ b/cmds/atrace/atrace.rc @@ -37,12 +37,18 @@ on late-init chmod 0666 /sys/kernel/tracing/events/sched/sched_process_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_waking/enable chmod 0666 /sys/kernel/tracing/events/sched/sched_waking/enable + chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/enable + chmod 0666 /sys/kernel/tracing/events/sched/sched_wakeup_new/enable chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable chmod 0666 /sys/kernel/tracing/events/cgroup/enable chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency/enable chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_idle/enable chmod 0666 /sys/kernel/tracing/events/power/cpu_idle/enable + chmod 0666 /sys/kernel/debug/tracing/events/power/clock_enable/enable + chmod 0666 /sys/kernel/tracing/events/power/clock_enable/enable + chmod 0666 /sys/kernel/debug/tracing/events/power/clock_disable/enable + chmod 0666 /sys/kernel/tracing/events/power/clock_disable/enable chmod 0666 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable @@ -79,6 +85,8 @@ on late-init chmod 0666 /sys/kernel/tracing/events/binder/binder_locked/enable chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable chmod 0666 /sys/kernel/tracing/events/binder/binder_unlock/enable + chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_set_priority/enable + chmod 0666 /sys/kernel/tracing/events/binder/binder_set_priority/enable chmod 0666 /sys/kernel/debug/tracing/events/i2c/enable chmod 0666 /sys/kernel/tracing/events/i2c/enable chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_read/enable @@ -125,6 +133,8 @@ on late-init chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable + chmod 0666 /sys/kernel/debug/tracing/events/oom/mark_victim/enable + chmod 0666 /sys/kernel/tracing/events/oom/mark_victim/enable chmod 0666 /sys/kernel/debug/tracing/events/task/task_rename/enable chmod 0666 /sys/kernel/tracing/events/task/task_rename/enable chmod 0666 /sys/kernel/debug/tracing/events/task/task_newtask/enable @@ -159,6 +169,12 @@ on late-init chmod 0666 /sys/kernel/tracing/events/ipi/ipi_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_raise/enable chmod 0666 /sys/kernel/tracing/events/ipi/ipi_raise/enable + chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_enable/enable + chmod 0666 /sys/kernel/tracing/events/clk/clk_disable/enable + chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_disable/enable + chmod 0666 /sys/kernel/tracing/events/clk/clk_enable/enable + chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable + chmod 0666 /sys/kernel/tracing/events/clk/clk_set_rate/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc index 6c86c21387..9186514d0a 100644 --- a/cmds/atrace/atrace_userdebug.rc +++ b/cmds/atrace/atrace_userdebug.rc @@ -18,8 +18,3 @@ on post-fs chmod 0666 /sys/kernel/tracing/events/filemap/enable chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable - # irq - chmod 0666 /sys/kernel/tracing/events/irq/enable - chmod 0666 /sys/kernel/debug/tracing/events/irq/enable - chmod 0666 /sys/kernel/tracing/events/ipi/enable - chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 990aa53071..45959e4cc9 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1657,8 +1657,6 @@ static Dumpstate::RunStatus dumpstate() { for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)"); - /* Dump Bluetooth HCI logs */ - ds.AddDir("/data/misc/bluetooth/logs", true); /* Dump Nfc NCI logs */ ds.AddDir("/data/misc/nfc/logs", true); @@ -1744,6 +1742,9 @@ static Dumpstate::RunStatus dumpstate() { RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal); + /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */ + ds.AddDir("/data/misc/bluetooth/logs", true); + if (ds.dump_pool_) { WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_); } else { diff --git a/cmds/idlcli/CommandVibrator.cpp b/cmds/idlcli/CommandVibrator.cpp index a7a70c38af..81bdbe25d7 100644 --- a/cmds/idlcli/CommandVibrator.cpp +++ b/cmds/idlcli/CommandVibrator.cpp @@ -22,7 +22,7 @@ namespace idlcli { class IdlCli; class CommandVibrator : public CommandWithSubcommands<CommandVibrator> { - std::string getDescription() const override { return "Invoke Vibrator HIDL APIs."; } + std::string getDescription() const override { return "Invoke Vibrator IDL APIs."; } std::string getUsageSummary() const override { return "<api> [arguments]"; } diff --git a/cmds/idlcli/IdlCli.h b/cmds/idlcli/IdlCli.h index dd8430415e..24a40d99e6 100644 --- a/cmds/idlcli/IdlCli.h +++ b/cmds/idlcli/IdlCli.h @@ -25,14 +25,47 @@ namespace idlcli { class IdlCli : public CommandWithSubcommands<IdlCli> { std::string getDescription() const override { return "Invoke IDL APIs."; } - std::string getUsageSummary() const override { return "<idl> [arguments]"; } + std::string getUsageSummary() const override { return "<idl> [options] [arguments]"; } UsageDetails getUsageDetails() const override { UsageDetails details{ + {"-n <name>", {"Get named service, rather than default."}}, {"<idl>", CommandRegistry<IdlCli>::List()}, }; return details; } + + Status doArgs(Args &args) override { + while (args.get<std::string>().value_or("").find("-") == 0) { + auto opt = *args.pop<std::string>(); + if (opt == "--") { + break; + } else if (opt == "-n") { + if (auto name = args.pop<decltype(mName)>()) { + mName = *name; + } else { + std::cerr << "Missing Value for Name!" << std::endl; + return USAGE; + } + } else { + std::cerr << "Invalid Option '" << opt << "'!" << std::endl; + return USAGE; + } + } + return CommandWithSubcommands::doArgs(args); + } + + IdlCli() {} + + std::string mName; + +public: + static IdlCli &Get() { + static IdlCli instance; + return instance; + } + + auto getName() { return mName; } }; } // namespace idlcli diff --git a/cmds/idlcli/main.cpp b/cmds/idlcli/main.cpp index 9ed9d8216a..308f294b8d 100644 --- a/cmds/idlcli/main.cpp +++ b/cmds/idlcli/main.cpp @@ -19,5 +19,5 @@ int main(const int argc, const char* const argv[]) { using namespace ::android::idlcli; - return IdlCli{}.main(Args{argc, argv}); + return IdlCli::Get().main(Args{argc, argv}); } diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h index b8744555e2..262f2e50b6 100644 --- a/cmds/idlcli/utils.h +++ b/cmds/idlcli/utils.h @@ -249,7 +249,7 @@ private: template <typename T> class CommandWithSubcommands : public Command { -private: +protected: Status doArgs(Args &args) override { mCommand = CommandRegistry<T>::Create(*args.get()); if (!mCommand) { diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h index 6c30a9e2ca..dfbb8863bd 100644 --- a/cmds/idlcli/vibrator.h +++ b/cmds/idlcli/vibrator.h @@ -13,24 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_ -#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_ +#pragma once #include <future> #include <aidl/android/hardware/vibrator/BnVibratorCallback.h> #include <aidl/android/hardware/vibrator/IVibrator.h> +#include <aidl/android/hardware/vibrator/IVibratorManager.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <android/hardware/vibrator/1.3/IVibrator.h> +#include "IdlCli.h" #include "utils.h" -#include "log/log.h" - namespace android { using hardware::Return; +using idlcli::IdlCli; static constexpr int NUM_TRIES = 2; @@ -47,20 +47,34 @@ inline ndk::ScopedAStatus NullptrStatus() { } template <typename I> -inline auto getService() { - return I::getService(); +inline auto getService(std::string name) { + const auto instance = std::string() + I::descriptor + "/" + name; + auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str())); + return I::fromBinder(vibBinder); } template <> -inline auto getService<aidl::android::hardware::vibrator::IVibrator>() { - const auto instance = - std::string() + aidl::android::hardware::vibrator::IVibrator::descriptor + "/default"; - auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str())); - return aidl::android::hardware::vibrator::IVibrator::fromBinder(vibBinder); +inline auto getService<android::hardware::vibrator::V1_0::IVibrator>(std::string name) { + return android::hardware::vibrator::V1_0::IVibrator::getService(name); +} + +template <> +inline auto getService<android::hardware::vibrator::V1_1::IVibrator>(std::string name) { + return android::hardware::vibrator::V1_1::IVibrator::getService(name); +} + +template <> +inline auto getService<android::hardware::vibrator::V1_2::IVibrator>(std::string name) { + return android::hardware::vibrator::V1_2::IVibrator::getService(name); +} + +template <> +inline auto getService<android::hardware::vibrator::V1_3::IVibrator>(std::string name) { + return android::hardware::vibrator::V1_3::IVibrator::getService(name); } template <typename I> -using shared_ptr = std::result_of_t<decltype(getService<I>)&()>; +using shared_ptr = std::result_of_t<decltype(getService<I>)&(std::string)>; template <typename I> class HalWrapper { @@ -68,7 +82,8 @@ public: static std::unique_ptr<HalWrapper> Create() { // Assume that if getService returns a nullptr, HAL is not available on the // device. - auto hal = getService<I>(); + const auto name = IdlCli::Get().getName(); + auto hal = getService<I>(name.empty() ? "default" : name); return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr; } @@ -121,5 +136,3 @@ private: } // namespace idlcli } // namespace android - -#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_ diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 83b6aa020c..9d88ca64e6 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -1,7 +1,16 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + 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/android/imagedecoder.h b/include/android/imagedecoder.h index cac67d4f8f..ee1eee2be6 100644 --- a/include/android/imagedecoder.h +++ b/include/android/imagedecoder.h @@ -367,6 +367,10 @@ int AImageDecoder_setDataSpace(AImageDecoder* _Nonnull decoder, int32_t dataspac * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or * after calling {@link AImageDecoder_rewind}). * + * It is strongly recommended to use setTargetSize only for downscaling, as it + * is often more efficient to scale-up when rendering than up-front due to + * reduced overall memory. + * * Available since API level 30. * * @param width Width of the output (prior to cropping). diff --git a/libs/attestation/Android.bp b/libs/attestation/Android.bp index b85aecd16d..ea3c341fe4 100644 --- a/libs/attestation/Android.bp +++ b/libs/attestation/Android.bp @@ -11,6 +11,15 @@ // 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libattestation", cflags: [ @@ -28,4 +37,4 @@ cc_library_static { "liblog", "libcrypto", ], -}
\ No newline at end of file +} diff --git a/libs/attestation/tests/Android.bp b/libs/attestation/tests/Android.bp index 6ce5ea1b2d..8dac0ce0fc 100644 --- a/libs/attestation/tests/Android.bp +++ b/libs/attestation/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libattestation_tests", test_suites: ["device-tests"], diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index 2e90142af6..1fbaa13887 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -22,10 +22,6 @@ "name": "binderParcelTest" }, { - "name": "binderParcelTest", - "host": true - }, - { "name": "binderLibTest" }, { diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 45807515e4..5df0012bd3 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -96,6 +96,22 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(con bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31); /** + * Returns all declared instances for a particular interface. + * + * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is + * passed here, then ["foo"] would be returned. + * + * See also AServiceManager_isDeclared. + * + * \param interface interface, e.g. 'android.foo.IFoo' + * \param context to pass to callback + * \param callback taking instance (e.g. 'foo') and context + */ +void AServiceManager_forEachDeclaredInstance(const char* interface, void* context, + void (*callback)(const char*, void*)) + __INTRODUCED_IN(31); + +/** * Prevent lazy services without client from shutting down their process * * \param persist 'true' if the process should not exit. diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index cef0bf31d2..8d08275eec 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -118,6 +118,7 @@ LIBBINDER_NDK31 { # introduced=31 AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex AServiceManager_isDeclared; # apex llndk + AServiceManager_forEachDeclaredInstance; # apex llndk AServiceManager_registerLazyService; # llndk AServiceManager_waitForService; # apex llndk AServiceManager_forceLazyServicesPersist; # llndk diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index cb0987e3e1..1ccd0d2a2b 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -19,6 +19,7 @@ #include "ibinder_internal.h" #include "status_internal.h" +#include <android-base/logging.h> #include <binder/IServiceManager.h> #include <binder/LazyServiceRegistrar.h> @@ -28,6 +29,7 @@ using ::android::IServiceManager; using ::android::sp; using ::android::status_t; using ::android::String16; +using ::android::String8; binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) { if (binder == nullptr || instance == nullptr) { @@ -92,6 +94,17 @@ bool AServiceManager_isDeclared(const char* instance) { sp<IServiceManager> sm = defaultServiceManager(); return sm->isDeclared(String16(instance)); } +void AServiceManager_forEachDeclaredInstance(const char* interface, void* context, + void (*callback)(const char*, void*)) { + CHECK(interface != nullptr); + // context may be nullptr + CHECK(callback != nullptr); + + sp<IServiceManager> sm = defaultServiceManager(); + for (const String16& instance : sm->getDeclaredInstances(String16(interface))) { + callback(String8(instance).c_str(), context); + } +} void AServiceManager_forceLazyServicesPersist(bool persist) { auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); serviceRegistrar.forcePersist(persist); @@ -110,4 +123,4 @@ bool AServiceManager_tryUnregister() { void AServiceManager_reRegister() { auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); serviceRegistrar.reRegister(); -}
\ No newline at end of file +} diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index de1a48dfd8..6a88401962 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -270,6 +270,25 @@ TEST(NdkBinder, DoubleNumber) { EXPECT_EQ(2, out); } +void defaultInstanceCounter(const char* instance, void* context) { + if (strcmp(instance, "default") == 0) { + ++*(size_t*)(context); + } +} + +TEST(NdkBinder, GetDeclaredInstances) { + bool hasLight = AServiceManager_isDeclared("android.hardware.light.ILights/default"); + + size_t count; + AServiceManager_forEachDeclaredInstance("android.hardware.light.ILights", &count, + defaultInstanceCounter); + + // At the time of writing this test, there is no good interface guaranteed + // to be on all devices. Cuttlefish has light, so this will generally test + // things. + EXPECT_EQ(count, hasLight ? 1 : 0); +} + TEST(NdkBinder, GetLazyService) { // Not declared in the vintf manifest ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService)); diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs index 2bf3d03a4b..f1b068ee43 100644 --- a/libs/binder/rust/tests/serialization.rs +++ b/libs/binder/rust/tests/serialization.rs @@ -40,6 +40,41 @@ mod bindings { include!(concat!(env!("OUT_DIR"), "/bindings.rs")); } +macro_rules! assert_eq { + ($left:expr, $right:expr $(,)?) => { + match (&$left, &$right) { + (left, right) => { + if *left != *right { + eprintln!( + "assertion failed: `{:?}` == `{:?}`, {}:{}:{}", + &*left, + &*right, + file!(), + line!(), + column!() + ); + return Err(StatusCode::FAILED_TRANSACTION); + } + } + } + }; +} + +macro_rules! assert { + ($expr:expr) => { + if !$expr { + eprintln!( + "assertion failed: `{:?}`, {}:{}:{}", + $expr, + file!(), + line!(), + column!() + ); + return Err(StatusCode::FAILED_TRANSACTION); + } + }; +} + static SERVICE_ONCE: Once = Once::new(); static mut SERVICE: Option<SpIBinder> = None; @@ -282,7 +317,7 @@ fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode, ))?; } bindings::Transaction_TEST_FAIL => { - return Err(StatusCode::FAILED_TRANSACTION) + assert!(false); } _ => return Err(StatusCode::UNKNOWN_TRANSACTION), } diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp index 5bccaca42d..97626bec7d 100644 --- a/libs/ftl/Android.bp +++ b/libs/ftl/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "ftl_test", test_suites: ["device-tests"], diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index debd664aba..dc91fc669c 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -143,7 +143,12 @@ cc_library_shared { aidl: { export_aidl_headers: true, - } + }, + + pgo: { + sampling: true, + profile_file: "libgui/libgui.profdata", + }, } // Used by media codec services exclusively as a static lib for diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 2e4f858a9d..05e19354da 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -17,15 +17,10 @@ // tag as surfaceflinger #define LOG_TAG "SurfaceFlinger" -#include <stdint.h> -#include <sys/types.h> - #include <android/gui/ITransactionTraceListener.h> - -#include <binder/Parcel.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> - +#include <binder/Parcel.h> #include <gui/IDisplayEventConnection.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IRegionSamplingListener.h> @@ -33,16 +28,15 @@ #include <gui/ISurfaceComposerClient.h> #include <gui/LayerDebugInfo.h> #include <gui/LayerState.h> - +#include <stdint.h> +#include <sys/types.h> #include <system/graphics.h> - #include <ui/DisplayMode.h> #include <ui/DisplayStatInfo.h> #include <ui/DisplayState.h> #include <ui/DynamicDisplayInfo.h> #include <ui/HdrCapabilities.h> #include <ui/StaticDisplayInfo.h> - #include <utils/Log.h> // --------------------------------------------------------------------------- @@ -411,24 +405,6 @@ public: return static_cast<status_t>(reply.readInt32()); } - status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display, - bool* outSupport) const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getAutoLowLatencyModeSupport failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_AUTO_LOW_LATENCY_MODE_SUPPORT, data, - &reply); - if (result != NO_ERROR) { - ALOGE("getAutoLowLatencyModeSupport failed to transact: %d", result); - return result; - } - return reply.readBool(outSupport); - } - void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -454,23 +430,6 @@ public: } } - status_t getGameContentTypeSupport(const sp<IBinder>& display, - bool* outSupport) const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getGameContentTypeSupport failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_GAME_CONTENT_TYPE_SUPPORT, data, &reply); - if (result != NO_ERROR) { - ALOGE("getGameContentTypeSupport failed to transact: %d", result); - return result; - } - return reply.readBool(outSupport); - } - void setGameContentType(const sp<IBinder>& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -796,6 +755,33 @@ public: return error; } + virtual status_t addFpsListener(const sp<IBinder>& layerHandle, + const sp<gui::IFpsListener>& listener) { + Parcel data, reply; + SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeStrongBinder, layerHandle); + SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); + const status_t error = + remote()->transact(BnSurfaceComposer::ADD_FPS_LISTENER, data, &reply); + if (error != OK) { + ALOGE("addFpsListener: Failed to transact"); + } + return error; + } + + virtual status_t removeFpsListener(const sp<gui::IFpsListener>& listener) { + Parcel data, reply; + SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); + + const status_t error = + remote()->transact(BnSurfaceComposer::REMOVE_FPS_LISTENER, data, &reply); + if (error != OK) { + ALOGE("removeFpsListener: Failed to transact"); + } + return error; + } + status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, @@ -1423,23 +1409,6 @@ status_t BnSurfaceComposer::onTransact( result = reply->writeInt32(result); return result; } - - case GET_AUTO_LOW_LATENCY_MODE_SUPPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getAutoLowLatencyModeSupport failed to readStrongBinder: %d", result); - return result; - } - bool supported = false; - result = getAutoLowLatencyModeSupport(display, &supported); - if (result == NO_ERROR) { - result = reply->writeBool(supported); - } - return result; - } - case SET_AUTO_LOW_LATENCY_MODE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = nullptr; @@ -1457,23 +1426,6 @@ status_t BnSurfaceComposer::onTransact( setAutoLowLatencyMode(display, setAllm); return result; } - - case GET_GAME_CONTENT_TYPE_SUPPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp<IBinder> display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getGameContentTypeSupport failed to readStrongBinder: %d", result); - return result; - } - bool supported = false; - result = getGameContentTypeSupport(display, &supported); - if (result == NO_ERROR) { - result = reply->writeBool(supported); - } - return result; - } - case SET_GAME_CONTENT_TYPE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = nullptr; @@ -1491,7 +1443,6 @@ status_t BnSurfaceComposer::onTransact( setGameContentType(display, setGameContentTypeOn); return result; } - case CLEAR_ANIMATION_FRAME_STATS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); status_t result = clearAnimationFrameStats(); @@ -1716,6 +1667,32 @@ status_t BnSurfaceComposer::onTransact( } return removeRegionSamplingListener(listener); } + case ADD_FPS_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<IBinder> layerHandle; + status_t result = data.readNullableStrongBinder(&layerHandle); + if (result != NO_ERROR) { + ALOGE("addFpsListener: Failed to read layer handle"); + return result; + } + sp<gui::IFpsListener> listener; + result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("addFpsListener: Failed to read listener"); + return result; + } + return addFpsListener(layerHandle, listener); + } + case REMOVE_FPS_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp<gui::IFpsListener> listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("removeFpsListener: Failed to read listener"); + return result; + } + return removeFpsListener(listener); + } case SET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> displayToken = data.readStrongBinder(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 1a643c2409..f5cde5932d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1904,22 +1904,10 @@ status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display, return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); } -bool SurfaceComposerClient::getAutoLowLatencyModeSupport(const sp<IBinder>& display) { - bool supported = false; - ComposerService::getComposerService()->getAutoLowLatencyModeSupport(display, &supported); - return supported; -} - void SurfaceComposerClient::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) { ComposerService::getComposerService()->setAutoLowLatencyMode(display, on); } -bool SurfaceComposerClient::getGameContentTypeSupport(const sp<IBinder>& display) { - bool supported = false; - ComposerService::getComposerService()->getGameContentTypeSupport(display, &supported); - return supported; -} - void SurfaceComposerClient::setGameContentType(const sp<IBinder>& display, bool on) { ComposerService::getComposerService()->setGameContentType(display, on); } @@ -1994,6 +1982,15 @@ status_t SurfaceComposerClient::removeRegionSamplingListener( return ComposerService::getComposerService()->removeRegionSamplingListener(listener); } +status_t SurfaceComposerClient::addFpsListener(const sp<IBinder>& layerHandle, + const sp<gui::IFpsListener>& listener) { + return ComposerService::getComposerService()->addFpsListener(layerHandle, listener); +} + +status_t SurfaceComposerClient::removeFpsListener(const sp<gui::IFpsListener>& listener) { + return ComposerService::getComposerService()->removeFpsListener(listener); +} + bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp<IBinder>& displayToken) { bool support = false; ComposerService::getComposerService()->getDisplayBrightnessSupport(displayToken, &support); diff --git a/aidl/gui/android/hardware/display/IDeviceProductInfoConstants.aidl b/libs/gui/aidl/android/gui/IFpsListener.aidl index 7cc272adff..63d333c940 100644 --- a/aidl/gui/android/hardware/display/IDeviceProductInfoConstants.aidl +++ b/libs/gui/aidl/android/gui/IFpsListener.aidl @@ -14,19 +14,11 @@ * limitations under the License. */ -package android.hardware.display; +package android.gui; /** @hide */ -interface IDeviceProductInfoConstants { - /** The device connection to the display sink is unknown. */ - const int CONNECTION_TO_SINK_UNKNOWN = 0; +oneway interface IFpsListener { - /** The device is built-in in the display sink. */ - const int CONNECTION_TO_SINK_BUILT_IN = 1; - - /** The device is directly connected to the display sink. */ - const int CONNECTION_TO_SINK_DIRECT = 2; - - /** The device is transitively connected to the display sink. */ - const int CONNECTION_TO_SINK_TRANSITIVE = 3; + // Reports the most recent recorded fps for the tree rooted at this layer + void onFpsReported(float fps); }
\ No newline at end of file diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index d0ab4802e1..8b64bcffca 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -16,21 +16,17 @@ #pragma once -#include <stdint.h> -#include <sys/types.h> - -#include <binder/IBinder.h> -#include <binder/IInterface.h> - +#include <android/gui/IFpsListener.h> #include <android/gui/IScreenCaptureListener.h> #include <android/gui/ITransactionTraceListener.h> +#include <binder/IBinder.h> +#include <binder/IInterface.h> #include <gui/FrameTimelineInfo.h> #include <gui/ITransactionCompletedListener.h> - #include <input/Flags.h> - #include <math/vec4.h> - +#include <stdint.h> +#include <sys/types.h> #include <ui/ConfigStoreTypes.h> #include <ui/DisplayId.h> #include <ui/DisplayMode.h> @@ -40,7 +36,6 @@ #include <ui/GraphicTypes.h> #include <ui/PixelFormat.h> #include <ui/Rotation.h> - #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/Timers.h> @@ -219,32 +214,17 @@ public: ui::ColorMode colorMode) = 0; /** - * Returns true if the connected display reports support for HDMI 2.1 Auto - * Low Latency Mode. - * For more information, see the HDMI 2.1 specification. - */ - virtual status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display, - bool* outSupport) const = 0; - - /** * Switches Auto Low Latency Mode on/off on the connected display, if it is - * available. This should only be called if #getAutoLowLatencyMode returns - * true. + * available. This should only be called if the display supports Auto Low + * Latency Mode as reported in #getDynamicDisplayInfo. * For more information, see the HDMI 2.1 specification. */ virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) = 0; /** - * Returns true if the connected display reports support for Game Content Type. - * For more information, see the HDMI 1.4 specification. - */ - virtual status_t getGameContentTypeSupport(const sp<IBinder>& display, - bool* outSupport) const = 0; - - /** * This will start sending infoframes to the connected display with - * ContentType=Game (if on=true). This will switch the disply to Game mode. - * This should only be called if #getGameContentTypeSupport returns true. + * ContentType=Game (if on=true). This should only be called if the display + * Game Content Type as reported in #getDynamicDisplayInfo. * For more information, see the HDMI 1.4 specification. */ virtual void setGameContentType(const sp<IBinder>& display, bool on) = 0; @@ -369,6 +349,23 @@ public: */ virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) = 0; + /* Registers a listener that streams fps updates from SurfaceFlinger. + * + * The listener will stream fps updates for the layer tree rooted at layerHandle. Usually, this + * should be tied to a task. Layers that are not descendants of that task are out of scope for + * FPS computations. + * + * Multiple listeners may be supported. + * + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t addFpsListener(const sp<IBinder>& layerHandle, + const sp<gui::IFpsListener>& listener) = 0; + /* + * Removes a listener that was streaming fps updates from SurfaceFlinger. + */ + virtual status_t removeFpsListener(const sp<gui::IFpsListener>& listener) = 0; + /* Sets the refresh rate boundaries for the display. * * The primary refresh rate range represents display manager's general guidance on the display @@ -563,9 +560,9 @@ public: CAPTURE_DISPLAY_BY_ID, NOTIFY_POWER_BOOST, SET_GLOBAL_SHADOW_SETTINGS, - GET_AUTO_LOW_LATENCY_MODE_SUPPORT, + GET_AUTO_LOW_LATENCY_MODE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. SET_AUTO_LOW_LATENCY_MODE, - GET_GAME_CONTENT_TYPE_SUPPORT, + GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. SET_GAME_CONTENT_TYPE, SET_FRAME_RATE, ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, @@ -574,6 +571,8 @@ public: GET_GPU_CONTEXT_PRIORITY, GET_EXTRA_BUFFER_COUNT, GET_DYNAMIC_DISPLAY_INFO, + ADD_FPS_LISTENER, + REMOVE_FPS_LISTENER, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6f0f18c131..ab0347c18f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -143,17 +143,11 @@ public: static status_t setActiveColorMode(const sp<IBinder>& display, ui::ColorMode colorMode); - // Reports whether the connected display supports Auto Low Latency Mode - static bool getAutoLowLatencyModeSupport(const sp<IBinder>& display); - // Switches on/off Auto Low Latency Mode on the connected display. This should only be // called if the connected display supports Auto Low Latency Mode as reported by // #getAutoLowLatencyModeSupport static void setAutoLowLatencyMode(const sp<IBinder>& display, bool on); - // Reports whether the connected display supports Game content type - static bool getGameContentTypeSupport(const sp<IBinder>& display); - // Turns Game mode on/off on the connected display. This should only be called // if the display supports Game content type, as reported by #getGameContentTypeSupport static void setGameContentType(const sp<IBinder>& display, bool on); @@ -595,6 +589,9 @@ public: const sp<IBinder>& stopLayerHandle, const sp<IRegionSamplingListener>& listener); static status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener); + static status_t addFpsListener(const sp<IBinder>& layerHandle, + const sp<gui::IFpsListener>& listener); + static status_t removeFpsListener(const sp<gui::IFpsListener>& listener); private: virtual void onFirstRef(); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3397198fa0..91b2affa2f 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -757,15 +757,7 @@ public: const sp<IScreenCaptureListener>& /* captureListener */) override { return NO_ERROR; } - status_t getAutoLowLatencyModeSupport(const sp<IBinder>& /*display*/, - bool* /*outSupport*/) const override { - return NO_ERROR; - } void setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {} - status_t getGameContentTypeSupport(const sp<IBinder>& /*display*/, - bool* /*outSupport*/) const override { - return NO_ERROR; - } void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {} status_t captureDisplay(uint64_t /*displayOrLayerStack*/, const sp<IScreenCaptureListener>& /* captureListener */) override { @@ -832,6 +824,11 @@ public: const sp<IRegionSamplingListener>& /*listener*/) override { return NO_ERROR; } + status_t addFpsListener(const sp<IBinder>& /*layerHandle*/, + const sp<gui::IFpsListener>& /*listener*/) { + return NO_ERROR; + } + status_t removeFpsListener(const sp<gui::IFpsListener>& /*listener*/) { return NO_ERROR; } status_t setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/, ui::DisplayModeId /*defaultMode*/, bool /*allowGroupSwitching*/, diff --git a/libs/math/Android.bp b/libs/math/Android.bp index 3cf9f3f97b..907eb67e9a 100644 --- a/libs/math/Android.bp +++ b/libs/math/Android.bp @@ -39,6 +39,7 @@ cc_library_static { "com.android.media.swcodec", "com.android.neuralnetworks", ], + min_sdk_version: "29", export_include_dirs: ["include"], @@ -49,4 +50,23 @@ cc_library_static { } } +cc_library_headers { + name: "libmath_headers", + export_include_dirs: ["include"], + host_supported: true, + vendor_available: true, + + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], + min_sdk_version: "apex_inherit", + + target: { + windows: { + enabled: true, + } + } +} + subdirs = ["tests"] diff --git a/libs/math/OWNERS b/libs/math/OWNERS index 6fb149a89c..72d33bc09e 100644 --- a/libs/math/OWNERS +++ b/libs/math/OWNERS @@ -1,6 +1,3 @@ -jaesoo@google.com -jiyong@google.com mathias@google.com -pawin@google.com randolphs@google.com romainguy@google.com diff --git a/libs/math/include/math/HashCombine.h b/libs/math/include/math/HashCombine.h new file mode 100644 index 0000000000..e91b52ba98 --- /dev/null +++ b/libs/math/include/math/HashCombine.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 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 <functional> + +namespace android { +static inline void hashCombineSingleHashed(size_t& combinedHash, size_t hash) { + combinedHash = 31 * combinedHash + hash; +} + +template<typename T> +static inline void hashCombineSingle(size_t& combinedHash, const T& val) { + hashCombineSingleHashed(combinedHash, std::hash<T>{}(val)); +} + +template<typename... Types> +static inline size_t hashCombine(const Types& ... args) { + size_t hash = 0; + ( hashCombineSingle(hash, args), ... ); + return hash; +} + +} // namespace android
\ No newline at end of file diff --git a/libs/math/include/math/TVecHelpers.h b/libs/math/include/math/TVecHelpers.h index 20f852fd9f..0dac662e97 100644 --- a/libs/math/include/math/TVecHelpers.h +++ b/libs/math/include/math/TVecHelpers.h @@ -19,9 +19,11 @@ #include <math.h> #include <stdint.h> +#include <math/HashCombine.h> #include <sys/types.h> #include <cmath> +#include <functional> #include <limits> #include <iostream> @@ -250,6 +252,17 @@ public: } return r; } + + // This isn't strictly a unary operator, but it is a common place shared between both + // matrix and vector classes + size_t hash() const { + VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this)); + size_t hashed = 0; + for (size_t i = 0; i < rv.size(); i++) { + android::hashCombineSingle(hashed, rv[i]); + } + return hashed; + } }; /* @@ -606,3 +619,16 @@ public: // ------------------------------------------------------------------------------------- } // namespace details } // namespace android + +namespace std { + template<template<typename T> class VECTOR, typename T> + struct hash<VECTOR<T>> { + static constexpr bool IS_VECTOR = + std::is_base_of<android::details::TVecUnaryOperators<VECTOR, T>, VECTOR<T>>::value; + + typename std::enable_if<IS_VECTOR, size_t>::type + operator()(const VECTOR<T>& v) const { + return v.hash(); + } + }; +} diff --git a/libs/math/include/math/half.h b/libs/math/include/math/half.h index 617a0ab5d2..5ec9bf7b40 100644 --- a/libs/math/include/math/half.h +++ b/libs/math/include/math/half.h @@ -17,6 +17,7 @@ #pragma once #include <stdint.h> +#include <functional> #include <iosfwd> #include <limits> #include <type_traits> @@ -202,6 +203,12 @@ public: inline static constexpr type signaling_NaN() noexcept { return android::half(android::half::binary, 0x7dff); } }; +template<> struct hash<android::half> { + size_t operator()(const android::half& half) { + return std::hash<float>{}(half); + } +}; + } // namespace std #ifdef LIKELY_DEFINED_LOCAL diff --git a/libs/math/tests/Android.bp b/libs/math/tests/Android.bp index 4a7c4dd8a4..14fb72af78 100644 --- a/libs/math/tests/Android.bp +++ b/libs/math/tests/Android.bp @@ -50,3 +50,10 @@ cc_test { static_libs: ["libmath"], cflags: ["-Wall", "-Werror"], } + +cc_test { + name: "hashcombine_test", + srcs: ["hashcombine_test.cpp"], + static_libs: ["libmath"], + cflags: ["-Wall", "-Werror"], +} diff --git a/libs/math/tests/half_test.cpp b/libs/math/tests/half_test.cpp index 604072e557..a514d986e4 100644 --- a/libs/math/tests/half_test.cpp +++ b/libs/math/tests/half_test.cpp @@ -94,4 +94,13 @@ TEST_F(HalfTest, Vec) { EXPECT_EQ(f4.xy, h2); } + +TEST_F(HalfTest, Hash) { + float4 f4a(1,2,3,4); + float4 f4b(2,2,3,4); + half4 h4a(f4a), h4b(f4b); + + EXPECT_NE(std::hash<half4>{}(h4a), std::hash<half4>{}(h4b)); +} + }; // namespace android diff --git a/libs/math/tests/hashcombine_test.cpp b/libs/math/tests/hashcombine_test.cpp new file mode 100644 index 0000000000..96c6e81588 --- /dev/null +++ b/libs/math/tests/hashcombine_test.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2021 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 "HashCombineTest" + +#include <math.h> +#include <stdlib.h> + +#include <math/half.h> +#include <math/vec4.h> + +#include <gtest/gtest.h> + +namespace android { + +class HashCombineTest : public testing::Test { +protected: +}; + +TEST_F(HashCombineTest, Basics) { + char a = 40; + int b = 32; + int c = 55; + float d = 42.f; + float d_ = 42.1f; + + EXPECT_NE(hashCombine(a, b, c, d), hashCombine(a, b, c, d_)); +} + +}; // namespace android diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 327b04c699..6c6db46fe4 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -404,10 +404,6 @@ bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) { return true; } -static bool hasUsage(const AHardwareBuffer_Desc& desc, uint64_t usage) { - return !!(desc.usage & usage); -} - static float toDegrees(uint32_t transform) { switch (transform) { case ui::Transform::ROT_90: @@ -454,11 +450,6 @@ static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destin sourceTransfer != destTransfer; } -static bool needsLinearEffect(const mat4& colorTransform, ui::Dataspace sourceDataspace, - ui::Dataspace destinationDataspace) { - return colorTransform != mat4() || needsToneMapping(sourceDataspace, destinationDataspace); -} - void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) { // Only run this if RE is running on its own thread. This way the access to GL // operations is guaranteed to be happening on the same thread. @@ -491,14 +482,19 @@ void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings* layer, const DisplaySettings& display, - bool undoPremultipliedAlpha) { + bool undoPremultipliedAlpha, + bool requiresLinearEffect) { if (layer->stretchEffect.hasEffect()) { // TODO: Implement } - if (mUseColorManagement && - needsLinearEffect(layer->colorTransform, layer->sourceDataspace, display.outputDataspace)) { - LinearEffect effect = LinearEffect{.inputDataspace = layer->sourceDataspace, - .outputDataspace = display.outputDataspace, + if (requiresLinearEffect) { + const ui::Dataspace inputDataspace = + mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::UNKNOWN; + const ui::Dataspace outputDataspace = + mUseColorManagement ? display.outputDataspace : ui::Dataspace::UNKNOWN; + + LinearEffect effect = LinearEffect{.inputDataspace = inputDataspace, + .outputDataspace = outputDataspace, .undoPremultipliedAlpha = undoPremultipliedAlpha}; auto effectIter = mRuntimeEffects.find(effect); @@ -556,6 +552,26 @@ void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& dis canvas->translate(-display.clip.left, -display.clip.top); } +class AutoSaveRestore { +public: + AutoSaveRestore(SkCanvas* canvas) : mCanvas(canvas) { mSaveCount = canvas->save(); } + ~AutoSaveRestore() { restore(); } + void replace(SkCanvas* canvas) { + mCanvas = canvas; + mSaveCount = canvas->save(); + } + void restore() { + if (mCanvas) { + mCanvas->restoreToCount(mSaveCount); + mCanvas = nullptr; + } + } + +private: + SkCanvas* mCanvas; + int mSaveCount; +}; + status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, const std::vector<const LayerSettings*>& layers, const sp<GraphicBuffer>& buffer, @@ -586,8 +602,6 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; AHardwareBuffer_Desc bufferDesc; AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc); - LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE), - "missing usage"); std::shared_ptr<AutoBackendTexture::LocalRef> surfaceTextureRef = nullptr; if (useFramebufferCache) { @@ -610,11 +624,10 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } } + const ui::Dataspace dstDataspace = + mUseColorManagement ? display.outputDataspace : ui::Dataspace::UNKNOWN; sk_sp<SkSurface> dstSurface = - surfaceTextureRef->getTexture()->getOrCreateSurface(mUseColorManagement - ? display.outputDataspace - : ui::Dataspace::UNKNOWN, - grContext.get()); + surfaceTextureRef->getTexture()->getOrCreateSurface(dstDataspace, grContext.get()); SkCanvas* dstCanvas = mCapture->tryCapture(dstSurface.get()); if (dstCanvas == nullptr) { @@ -650,7 +663,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } } - canvas->save(); + AutoSaveRestore surfaceAutoSaveRestore(canvas); // Clear the entire canvas with a transparent black to prevent ghost images. canvas->clear(SK_ColorTRANSPARENT); initCanvas(canvas, display); @@ -671,13 +684,18 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; sk_sp<SkShader> shader = SkShaders::Color(SkColor4f{.fR = 0., .fG = 0., .fB = 0., .fA = 1.0}, - toSkColorSpace(mUseColorManagement ? display.outputDataspace - : ui::Dataspace::UNKNOWN)); + toSkColorSpace(dstDataspace)); paint.setShader(shader); clearRegion.setRects(skRects, numRects); canvas->drawRegion(clearRegion, paint); } + // setup color filter if necessary + sk_sp<SkColorFilter> displayColorTransform; + if (display.colorTransform != mat4()) { + displayColorTransform = SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)); + } + for (const auto& layer : layers) { ATRACE_NAME("DrawLayer"); @@ -705,7 +723,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, // assign dstCanvas to canvas and ensure that the canvas state is up to date canvas = dstCanvas; - canvas->save(); + surfaceAutoSaveRestore.replace(canvas); initCanvas(canvas, display); LOG_ALWAYS_FATAL_IF(activeSurface->getCanvas()->getSaveCount() != @@ -717,7 +735,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, activeSurface = dstSurface; } - canvas->save(); + SkAutoCanvasRestore layerAutoSaveRestore(canvas, true); if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; @@ -765,15 +783,34 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } } - const ui::Dataspace targetDataspace = mUseColorManagement - ? (needsLinearEffect(layer->colorTransform, layer->sourceDataspace, - display.outputDataspace) - // If we need to map to linear space, then mark the source image with the - // same colorspace as the destination surface so that Skia's color - // management is a no-op. - ? display.outputDataspace - : layer->sourceDataspace) - : ui::Dataspace::UNKNOWN; + // Shadows are assumed to live only on their own layer - it's not valid + // to draw the boundary rectangles when there is already a caster shadow + // TODO(b/175915334): consider relaxing this restriction to enable more flexible + // composition - using a well-defined invalid color is long-term less error-prone. + if (layer->shadow.length > 0) { + const auto rect = layer->geometry.roundedCornersRadius > 0 + ? getSkRect(layer->geometry.roundedCornersCrop) + : bounds; + drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow); + continue; + } + + const bool requiresLinearEffect = layer->colorTransform != mat4() || + (mUseColorManagement && + needsToneMapping(layer->sourceDataspace, display.outputDataspace)); + + // quick abort from drawing the remaining portion of the layer + if (layer->alpha == 0 && !requiresLinearEffect && + (!displayColorTransform || displayColorTransform->isAlphaUnchanged())) { + continue; + } + + // If we need to map to linear space or color management is disabled, then mark the source + // image with the same colorspace as the destination surface so that Skia's color + // management is a no-op. + const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect) + ? dstDataspace + : layer->sourceDataspace; SkPaint paint; if (layer->source.buffer.buffer) { @@ -792,7 +829,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } sk_sp<SkImage> image = - imageTextureRef->getTexture()->makeImage(targetDataspace, + imageTextureRef->getTexture()->makeImage(layerDataspace, item.usePremultipliedAlpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType, @@ -848,12 +885,12 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, if (item.isOpaque) { shader = SkShaders::Blend(SkBlendMode::kPlus, shader, SkShaders::Color(SkColors::kBlack, - toSkColorSpace(targetDataspace))); + toSkColorSpace(layerDataspace))); } - paint.setShader( - createRuntimeEffectShader(shader, layer, display, - !item.isOpaque && item.usePremultipliedAlpha)); + paint.setShader(createRuntimeEffectShader(shader, layer, display, + !item.isOpaque && item.usePremultipliedAlpha, + requiresLinearEffect)); paint.setAlphaf(layer->alpha); } else { ATRACE_NAME("DrawColor"); @@ -862,35 +899,22 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, .fG = color.g, .fB = color.b, .fA = layer->alpha}, - toSkColorSpace(targetDataspace)); + toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, - /* undoPremultipliedAlpha */ false)); + /* undoPremultipliedAlpha */ false, + requiresLinearEffect)); } - sk_sp<SkColorFilter> filter = - SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)); + paint.setColorFilter(displayColorTransform); - paint.setColorFilter(filter); - - if (layer->shadow.length > 0) { - const auto rect = layer->geometry.roundedCornersRadius > 0 - ? getSkRect(layer->geometry.roundedCornersCrop) - : bounds; - drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow); + if (layer->geometry.roundedCornersRadius > 0) { + paint.setAntiAlias(true); + canvas->drawRRect(getRoundedRect(layer), paint); } else { - // Shadows are assumed to live only on their own layer - it's not valid - // to draw the boundary retangles when there is already a caster shadow - // TODO(b/175915334): consider relaxing this restriction to enable more flexible - // composition - using a well-defined invalid color is long-term less error-prone. - // Push the clipRRect onto the clip stack. Draw the image. Pop the clip. - if (layer->geometry.roundedCornersRadius > 0) { - canvas->clipRRect(getRoundedRect(layer), true); - } canvas->drawRect(bounds, paint); } - canvas->restore(); } - canvas->restore(); + surfaceAutoSaveRestore.restore(); mCapture->endCapture(); { ATRACE_NAME("flush surface"); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index 5779ae679b..ad26206a8f 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -92,11 +92,12 @@ private: void initCanvas(SkCanvas* canvas, const DisplaySettings& display); void drawShadow(SkCanvas* canvas, const SkRect& casterRect, float casterCornerRadius, const ShadowSettings& shadowSettings); - // If mUseColorManagement is correct and layer needsLinearEffect, it returns a linear runtime - // shader. Otherwise it returns the input shader. + // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. + // Otherwise it returns the input shader. sk_sp<SkShader> createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings* layer, const DisplaySettings& display, - bool undoPremultipliedAlpha); + bool undoPremultipliedAlpha, + bool requiresLinearEffect); EGLDisplay mEGLDisplay; EGLContext mEGLContext; diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index ac0ae72f29..de2b9a406b 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -238,9 +238,11 @@ cc_library_headers { }, header_libs: [ "libnativewindow_headers", + "libmath_headers", ], export_header_lib_headers: [ "libnativewindow_headers", + "libmath_headers", ], min_sdk_version: "29", } diff --git a/libs/ui/DynamicDisplayInfo.cpp b/libs/ui/DynamicDisplayInfo.cpp index 11acdae921..d5c4ef0c17 100644 --- a/libs/ui/DynamicDisplayInfo.cpp +++ b/libs/ui/DynamicDisplayInfo.cpp @@ -39,7 +39,9 @@ size_t DynamicDisplayInfo::getFlattenedSize() const { FlattenableHelpers::getFlattenedSize(activeDisplayModeId) + FlattenableHelpers::getFlattenedSize(supportedColorModes) + FlattenableHelpers::getFlattenedSize(activeColorMode) + - FlattenableHelpers::getFlattenedSize(hdrCapabilities); + FlattenableHelpers::getFlattenedSize(hdrCapabilities) + + FlattenableHelpers::getFlattenedSize(autoLowLatencyModeSupported) + + FlattenableHelpers::getFlattenedSize(gameContentTypeSupported); } status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const { @@ -51,6 +53,8 @@ status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const { RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedColorModes)); RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeColorMode)); RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, hdrCapabilities)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, autoLowLatencyModeSupported)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, gameContentTypeSupported)); return OK; } @@ -60,6 +64,8 @@ status_t DynamicDisplayInfo::unflatten(const void* buffer, size_t size) { RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedColorModes)); RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeColorMode)); RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &hdrCapabilities)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &autoLowLatencyModeSupported)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &gameContentTypeSupported)); return OK; } diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS index 5110a6c8a7..a0b5fe7119 100644 --- a/libs/ui/OWNERS +++ b/libs/ui/OWNERS @@ -1,3 +1,4 @@ +adyabr@google.com alecmouri@google.com chrisforbes@google.com jreck@google.com diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h index 6c349b749d..a4c2f71a4c 100644 --- a/libs/ui/include/ui/DynamicDisplayInfo.h +++ b/libs/ui/include/ui/DynamicDisplayInfo.h @@ -41,6 +41,14 @@ struct DynamicDisplayInfo : LightFlattenable<DynamicDisplayInfo> { ui::ColorMode activeColorMode; HdrCapabilities hdrCapabilities; + // True if the display reports support for HDMI 2.1 Auto Low Latency Mode. + // For more information, see the HDMI 2.1 specification. + bool autoLowLatencyModeSupported; + + // True if the display reports support for Game Content Type. + // For more information, see the HDMI 1.4 specification. + bool gameContentTypeSupported; + std::optional<ui::DisplayMode> getActiveDisplayMode() const; bool isFixedSize() const { return false; } diff --git a/libs/ui/include/ui/FloatRect.h b/libs/ui/include/ui/FloatRect.h index 5d329ea6a9..4c9c7b7ef1 100644 --- a/libs/ui/include/ui/FloatRect.h +++ b/libs/ui/include/ui/FloatRect.h @@ -16,6 +16,7 @@ #pragma once +#include <math/HashCombine.h> #include <ostream> namespace android { @@ -62,3 +63,13 @@ static inline void PrintTo(const FloatRect& rect, ::std::ostream* os) { } } // namespace android + +namespace std { + +template <> +struct hash<android::FloatRect> { + size_t operator()(const android::FloatRect& rect) const { + return android::hashCombine(rect.left, rect.top, rect.right, rect.bottom); + } +}; +} // namespace std diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h index 58323e553e..9e24a077ff 100644 --- a/libs/ui/include/ui/Rect.h +++ b/libs/ui/include/ui/Rect.h @@ -24,6 +24,7 @@ #include <utils/Log.h> #include <utils/TypeHelpers.h> +#include <math/HashCombine.h> #include <ui/FloatRect.h> #include <ui/Point.h> #include <ui/Size.h> @@ -234,4 +235,13 @@ ANDROID_BASIC_TYPES_TRAITS(Rect) }; // namespace android +namespace std { +template <> +struct hash<android::Rect> { + size_t operator()(const android::Rect& rect) const { + return android::hashCombine(rect.left, rect.top, rect.right, rect.bottom); + } +}; +} // namespace std + #endif // ANDROID_UI_RECT diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h index 6bb7b8d21c..927c334c85 100644 --- a/libs/ui/include/ui/Region.h +++ b/libs/ui/include/ui/Region.h @@ -21,6 +21,7 @@ #include <sys/types.h> #include <ostream> +#include <math/HashCombine.h> #include <ui/Rect.h> #include <utils/Flattenable.h> @@ -234,4 +235,17 @@ static inline void PrintTo(const Region& region, ::std::ostream* os) { // --------------------------------------------------------------------------- }; // namespace android +namespace std { +template <> +struct hash<android::Region> { + size_t operator()(const android::Region& region) const { + size_t hash = 0; + for (const android::Rect& rect : region) { + android::hashCombineSingle(hash, rect); + } + return hash; + } +}; +} // namespace std + #endif // ANDROID_UI_REGION_H diff --git a/libs/ui/tests/Rect_test.cpp b/libs/ui/tests/Rect_test.cpp index 5499a5b507..9cc36bb15b 100644 --- a/libs/ui/tests/Rect_test.cpp +++ b/libs/ui/tests/Rect_test.cpp @@ -259,4 +259,33 @@ TEST(RectTest, toFloatRect) { EXPECT_EQ(FloatRect(10.f, 20.f, 50.f, 60.f), floatRect); } +TEST(RectTest, RectHash) { + const std::vector<Rect> rects = { + Rect(10, 20, 50, 60), Rect(11, 20, 50, 60), Rect(11, 21, 50, 60), + Rect(11, 21, 51, 60), Rect(11, 21, 51, 61), + }; + + for (const auto& a : rects) { + for (const auto& b : rects) { + const bool hashEq = std::hash<Rect>{}(a) == std::hash<Rect>{}(b); + EXPECT_EQ(a == b, hashEq); + } + } +} + +TEST(RectTest, FloatRectHash) { + const std::vector<FloatRect> floatRects = { + Rect(10, 20, 50, 60).toFloatRect(), Rect(11, 20, 50, 60).toFloatRect(), + Rect(11, 21, 50, 60).toFloatRect(), Rect(11, 21, 51, 60).toFloatRect(), + Rect(11, 21, 51, 61).toFloatRect(), + }; + + for (const auto& a : floatRects) { + for (const auto& b : floatRects) { + const bool hashEq = std::hash<FloatRect>{}(a) == std::hash<FloatRect>{}(b); + EXPECT_EQ(a == b, hashEq); + } + } +} + } // namespace android::ui diff --git a/libs/ui/tests/Region_test.cpp b/libs/ui/tests/Region_test.cpp index c6b826d66e..74924bdce8 100644 --- a/libs/ui/tests/Region_test.cpp +++ b/libs/ui/tests/Region_test.cpp @@ -167,5 +167,17 @@ TEST_F(RegionTest, EqualsToSelf) { ASSERT_TRUE(touchableRegion.contains(50, 50)); } +TEST_F(RegionTest, RegionHash) { + Region region1; + region1.addRectUnchecked(10, 20, 30, 40); + region1.addRectUnchecked(40, 30, 20, 10); + + Region region2; + region2.addRectUnchecked(11, 20, 30, 40); + region2.addRectUnchecked(40, 31, 20, 10); + + EXPECT_NE(std::hash<Region>{}(region1), std::hash<Region>{}(region2)); +} + }; // namespace android diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 4b1f350631..33b3e1ee2f 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -50,9 +50,10 @@ void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& li // --- NotifyKeyArgs --- -NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, - int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags, - int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) +NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, + uint32_t source, int32_t displayId, uint32_t policyFlags, + int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, + int32_t metaState, nsecs_t downTime) : NotifyArgs(id, eventTime), deviceId(deviceId), source(source), @@ -63,7 +64,8 @@ NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, ui keyCode(keyCode), scanCode(scanCode), metaState(metaState), - downTime(downTime) {} + downTime(downTime), + readTime(readTime) {} NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) : NotifyArgs(other.id, other.eventTime), @@ -76,13 +78,15 @@ NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) keyCode(other.keyCode), scanCode(other.scanCode), metaState(other.metaState), - downTime(other.downTime) {} + downTime(other.downTime), + readTime(other.readTime) {} bool NotifyKeyArgs::operator==(const NotifyKeyArgs& rhs) const { - return id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId && - source == rhs.source && displayId == rhs.displayId && policyFlags == rhs.policyFlags && - action == rhs.action && flags == rhs.flags && keyCode == rhs.keyCode && - scanCode == rhs.scanCode && metaState == rhs.metaState && downTime == rhs.downTime; + return id == rhs.id && eventTime == rhs.eventTime && readTime == rhs.readTime && + deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId && + policyFlags == rhs.policyFlags && action == rhs.action && flags == rhs.flags && + keyCode == rhs.keyCode && scanCode == rhs.scanCode && metaState == rhs.metaState && + downTime == rhs.downTime; } void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { @@ -91,16 +95,14 @@ void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const { // --- NotifyMotionArgs --- -NotifyMotionArgs::NotifyMotionArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, - int32_t displayId, uint32_t policyFlags, int32_t action, - int32_t actionButton, int32_t flags, int32_t metaState, - int32_t buttonState, MotionClassification classification, - int32_t edgeFlags, uint32_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords, float xPrecision, - float yPrecision, float xCursorPosition, float yCursorPosition, - nsecs_t downTime, - const std::vector<TouchVideoFrame>& videoFrames) +NotifyMotionArgs::NotifyMotionArgs( + int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, uint32_t source, + int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton, + int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification, + int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties, + const PointerCoords* pointerCoords, float xPrecision, float yPrecision, + float xCursorPosition, float yCursorPosition, nsecs_t downTime, + const std::vector<TouchVideoFrame>& videoFrames) : NotifyArgs(id, eventTime), deviceId(deviceId), source(source), @@ -119,6 +121,7 @@ NotifyMotionArgs::NotifyMotionArgs(int32_t id, nsecs_t eventTime, int32_t device xCursorPosition(xCursorPosition), yCursorPosition(yCursorPosition), downTime(downTime), + readTime(readTime), videoFrames(videoFrames) { for (uint32_t i = 0; i < pointerCount; i++) { this->pointerProperties[i].copyFrom(pointerProperties[i]); @@ -145,6 +148,7 @@ NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) xCursorPosition(other.xCursorPosition), yCursorPosition(other.yCursorPosition), downTime(other.downTime), + readTime(other.readTime), videoFrames(other.videoFrames) { for (uint32_t i = 0; i < pointerCount; i++) { pointerProperties[i].copyFrom(other.pointerProperties[i]); @@ -157,11 +161,12 @@ static inline bool isCursorPositionEqual(float lhs, float rhs) { } bool NotifyMotionArgs::operator==(const NotifyMotionArgs& rhs) const { - bool equal = id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId && - source == rhs.source && displayId == rhs.displayId && policyFlags == rhs.policyFlags && - action == rhs.action && actionButton == rhs.actionButton && flags == rhs.flags && - metaState == rhs.metaState && buttonState == rhs.buttonState && - classification == rhs.classification && edgeFlags == rhs.edgeFlags && + bool equal = id == rhs.id && eventTime == rhs.eventTime && readTime == rhs.readTime && + deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId && + policyFlags == rhs.policyFlags && action == rhs.action && + actionButton == rhs.actionButton && flags == rhs.flags && metaState == rhs.metaState && + buttonState == rhs.buttonState && classification == rhs.classification && + edgeFlags == rhs.edgeFlags && pointerCount == rhs.pointerCount // PointerProperties and PointerCoords are compared separately below && xPrecision == rhs.xPrecision && yPrecision == rhs.yPrecision && diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index d6b7259148..b2ddb42eab 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -105,7 +105,7 @@ private: void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) override {} - void pokeUserActivity(nsecs_t, int32_t) override {} + void pokeUserActivity(nsecs_t, int32_t, int32_t) override {} bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; } @@ -249,8 +249,9 @@ static NotifyMotionArgs generateMotionArgs() { const nsecs_t currentTime = now(); // Define a valid motion event. - NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, POLICY_FLAG_PASS_TO_USER, AMOTION_EVENT_ACTION_DOWN, + NotifyMotionArgs args(/* id */ 0, currentTime, currentTime, DEVICE_ID, + AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, POLICY_FLAG_PASS_TO_USER, + AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties, pointerCoords, diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 45a007ba6e..ed17e68f9e 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -273,6 +273,7 @@ struct CommandEntry { bool enabled; int32_t pid; nsecs_t consumeTime; // time when the event was consumed by InputConsumer + int32_t displayId; }; } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 9898e9d820..d0a5c09c80 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2591,6 +2591,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { std::make_unique<CommandEntry>(&InputDispatcher::doPokeUserActivityLockedInterruptible); commandEntry->eventTime = eventEntry.eventTime; commandEntry->userActivityEventType = eventType; + commandEntry->displayId = displayId; postCommandLocked(std::move(commandEntry)); } @@ -5715,7 +5716,8 @@ bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); - mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType); + mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType, + commandEntry->displayId); mLock.lock(); } diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 909ce54e4b..439d85e06e 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -134,7 +134,7 @@ public: uint32_t policyFlags) = 0; /* Poke user activity for an event dispatched to a window. */ - virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0; + virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) = 0; /* Checks whether a given application pid/uid has permission to inject input events * into other applications. diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h index 094bc0c1dd..4b7d26df2b 100644 --- a/services/inputflinger/include/InputListener.h +++ b/services/inputflinger/include/InputListener.h @@ -73,12 +73,14 @@ struct NotifyKeyArgs : public NotifyArgs { int32_t scanCode; int32_t metaState; nsecs_t downTime; + nsecs_t readTime; inline NotifyKeyArgs() { } - NotifyKeyArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, - int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags, - int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime); + NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, + uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action, + int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, + nsecs_t downTime); bool operator==(const NotifyKeyArgs& rhs) const; @@ -120,13 +122,14 @@ struct NotifyMotionArgs : public NotifyArgs { float xCursorPosition; float yCursorPosition; nsecs_t downTime; + nsecs_t readTime; std::vector<TouchVideoFrame> videoFrames; inline NotifyMotionArgs() { } - NotifyMotionArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, - int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton, - int32_t flags, int32_t metaState, int32_t buttonState, + NotifyMotionArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, + uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action, + int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords, float xPrecision, float yPrecision, float xCursorPosition, diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index e939d1cb91..d0a9ca72e4 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -37,6 +37,7 @@ // #define LOG_NDEBUG 0 #include <android-base/file.h> +#include <android-base/strings.h> #include <android-base/stringprintf.h> #include <cutils/properties.h> #include <input/KeyCharacterMap.h> @@ -1361,13 +1362,14 @@ std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const { // Some devices report battery capacity as an integer through the "capacity" file if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity", &buffer)) { - return std::stoi(buffer); + return std::stoi(base::Trim(buffer)); } // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX // These values are taken from kernel source code include/linux/power_supply.h if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity_level", &buffer)) { - const auto it = BATTERY_LEVEL.find(buffer); + // Remove any white space such as trailing new line + const auto it = BATTERY_LEVEL.find(base::Trim(buffer)); if (it != BATTERY_LEVEL.end()) { return it->second; } @@ -1389,9 +1391,8 @@ std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const { return std::nullopt; } - // Remove trailing new line - buffer.erase(std::remove(buffer.begin(), buffer.end(), '\n'), buffer.end()); - const auto it = BATTERY_STATUS.find(buffer); + // Remove white space like trailing new line + const auto it = BATTERY_STATUS.find(base::Trim(buffer)); if (it != BATTERY_STATUS.end()) { return it->second; @@ -1567,6 +1568,7 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz for (size_t i = 0; i < count; i++) { struct input_event& iev = readBuffer[i]; event->when = processEventTimestamp(iev); + event->readTime = systemTime(SYSTEM_TIME_MONOTONIC); event->deviceId = deviceId; event->type = iev.type; event->code = iev.code; diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index cbf3b69f29..dd1abeb7a4 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -506,8 +506,8 @@ void InputDevice::flushSensor(InputDeviceSensorType sensorType) { for_each_mapper([sensorType](InputMapper& mapper) { mapper.flushSensor(sensorType); }); } -void InputDevice::cancelTouch(nsecs_t when) { - for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); }); +void InputDevice::cancelTouch(nsecs_t when, nsecs_t readTime) { + for_each_mapper([when, readTime](InputMapper& mapper) { mapper.cancelTouch(when, readTime); }); } std::optional<int32_t> InputDevice::getBatteryCapacity() { diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index e6164d38d4..4059729ae0 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -53,7 +53,11 @@ static constexpr size_t COLOR_NUM = 3; * A raw event as retrieved from the EventHub. */ struct RawEvent { + // Time when the event happened nsecs_t when; + // Time when the event was read by EventHub. Only populated for input events. + // For other events (device added/removed/etc), this value is undefined and should not be read. + nsecs_t readTime; int32_t deviceId; int32_t type; int32_t code; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 34c330b89c..863cd41fc9 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -86,7 +86,7 @@ public: void cancelVibrate(int32_t token); bool isVibrating(); std::vector<int32_t> getVibratorIds(); - void cancelTouch(nsecs_t when); + void cancelTouch(nsecs_t when, nsecs_t readTime); bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, std::chrono::microseconds maxBatchReportLatency); void disableSensor(InputDeviceSensorType sensorType); @@ -351,7 +351,7 @@ public: inline std::optional<DisplayViewport> getAssociatedViewport() const { return mDevice.getAssociatedViewport(); } - inline void cancelTouch(nsecs_t when) { mDevice.cancelTouch(when); } + inline void cancelTouch(nsecs_t when, nsecs_t readTime) { mDevice.cancelTouch(when, readTime); } inline void bumpGeneration() { mDevice.bumpGeneration(); } inline const PropertyMap& getConfiguration() { return mDevice.getConfiguration(); } diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp index 254b64b4d9..bb12be7ee2 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp @@ -265,11 +265,11 @@ void CursorInputMapper::process(const RawEvent* rawEvent) { mCursorScrollAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - sync(rawEvent->when); + sync(rawEvent->when, rawEvent->readTime); } } -void CursorInputMapper::sync(nsecs_t when) { +void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) { int32_t lastButtonState = mButtonState; int32_t currentButtonState = mCursorButtonAccumulator.getButtonState(); mButtonState = currentButtonState; @@ -362,8 +362,8 @@ void CursorInputMapper::sync(nsecs_t when) { } // Synthesize key down from buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, - displayId, policyFlags, lastButtonState, currentButtonState); + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(), + mSource, displayId, policyFlags, lastButtonState, currentButtonState); // Send motion event. if (downChanged || moved || scrolled || buttonsChanged) { @@ -383,8 +383,8 @@ void CursorInputMapper::sync(nsecs_t when) { while (!released.isEmpty()) { int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit()); buttonState &= ~actionButton; - NotifyMotionArgs releaseArgs(getContext()->getNextId(), when, getDeviceId(), - mSource, displayId, policyFlags, + NotifyMotionArgs releaseArgs(getContext()->getNextId(), when, readTime, + getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0, metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, @@ -395,11 +395,11 @@ void CursorInputMapper::sync(nsecs_t when) { } } - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, motionEventAction, 0, 0, metaState, currentButtonState, - MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, - &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, - xCursorPosition, yCursorPosition, downTime, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, motionEventAction, 0, 0, metaState, + currentButtonState, MotionClassification::NONE, + AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, + mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime, /* videoFrames */ {}); getListener()->notifyMotion(&args); @@ -408,8 +408,8 @@ void CursorInputMapper::sync(nsecs_t when) { while (!pressed.isEmpty()) { int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit()); buttonState |= actionButton; - NotifyMotionArgs pressArgs(getContext()->getNextId(), when, getDeviceId(), mSource, - displayId, policyFlags, + NotifyMotionArgs pressArgs(getContext()->getNextId(), when, readTime, getDeviceId(), + mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0, metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, @@ -424,9 +424,10 @@ void CursorInputMapper::sync(nsecs_t when) { // Send hover move after UP to tell the application that the mouse is hovering now. if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) { - NotifyMotionArgs hoverArgs(getContext()->getNextId(), when, getDeviceId(), mSource, - displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, - 0, metaState, currentButtonState, MotionClassification::NONE, + NotifyMotionArgs hoverArgs(getContext()->getNextId(), when, readTime, getDeviceId(), + mSource, displayId, policyFlags, + AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, + currentButtonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime, /* videoFrames */ {}); @@ -438,9 +439,10 @@ void CursorInputMapper::sync(nsecs_t when) { pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, getDeviceId(), mSource, - displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, - metaState, currentButtonState, MotionClassification::NONE, + NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, readTime, getDeviceId(), + mSource, displayId, policyFlags, + AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, + currentButtonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime, /* videoFrames */ {}); @@ -449,7 +451,7 @@ void CursorInputMapper::sync(nsecs_t when) { } // Synthesize key up from buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(), mSource, displayId, policyFlags, lastButtonState, currentButtonState); mCursorMotionAccumulator.finishSync(); diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h index 05bbb26716..9a8ca01294 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.h +++ b/services/inputflinger/reader/mapper/CursorInputMapper.h @@ -114,7 +114,7 @@ private: void configureParameters(); void dumpParameters(std::string& dump); - void sync(nsecs_t when); + void sync(nsecs_t when, nsecs_t readTime); }; } // namespace android diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp index 1ce54ae2dd..df1acd439f 100644 --- a/services/inputflinger/reader/mapper/InputMapper.cpp +++ b/services/inputflinger/reader/mapper/InputMapper.cpp @@ -68,7 +68,7 @@ std::vector<int32_t> InputMapper::getVibratorIds() { return {}; } -void InputMapper::cancelTouch(nsecs_t when) {} +void InputMapper::cancelTouch(nsecs_t when, nsecs_t readTime) {} bool InputMapper::enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index bd543e5798..15cff1cfca 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -67,7 +67,7 @@ public: virtual void cancelVibrate(int32_t token); virtual bool isVibrating(); virtual std::vector<int32_t> getVibratorIds(); - virtual void cancelTouch(nsecs_t when); + virtual void cancelTouch(nsecs_t when, nsecs_t readTime); virtual bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, std::chrono::microseconds maxBatchReportLatency); diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp index 37aa140c16..0dc312ecd2 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp @@ -299,14 +299,14 @@ void JoystickInputMapper::process(const RawEvent* rawEvent) { case EV_SYN: switch (rawEvent->code) { case SYN_REPORT: - sync(rawEvent->when, false /*force*/); + sync(rawEvent->when, rawEvent->readTime, false /*force*/); break; } break; } } -void JoystickInputMapper::sync(nsecs_t when, bool force) { +void JoystickInputMapper::sync(nsecs_t when, nsecs_t readTime, bool force) { if (!filterAxes(force)) { return; } @@ -337,9 +337,10 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) { // TODO: Use the input device configuration to control this behavior more finely. uint32_t policyFlags = 0; - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, - ADISPLAY_ID_NONE, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, - buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), + AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags, + AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, + MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {}); diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h index 0cf60a27d8..bba95addc4 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.h +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h @@ -92,7 +92,7 @@ private: // Axes indexed by raw ABS_* axis index. std::unordered_map<int32_t, Axis> mAxes; - void sync(nsecs_t when, bool force); + void sync(nsecs_t when, nsecs_t readTime, bool force); bool haveAxis(int32_t axisId); void pruneAxes(bool ignoreExplicitlyMappedAxes); diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 8b9f235438..2c5a576160 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -216,7 +216,8 @@ void KeyboardInputMapper::process(const RawEvent* rawEvent) { mCurrentHidUsage = 0; if (isKeyboardOrGamepadKey(scanCode)) { - processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode); + processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode, + usageCode); } break; } @@ -269,7 +270,8 @@ bool KeyboardInputMapper::isMediaKey(int32_t keyCode) { return false; } -void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) { +void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode, + int32_t usageCode) { int32_t keyCode; int32_t keyMetaState; uint32_t policyFlags; @@ -299,7 +301,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, return; } if (policyFlags & POLICY_FLAG_GESTURE) { - getDeviceContext().cancelTouch(when); + getDeviceContext().cancelTouch(when, readTime); } KeyDown keyDown; @@ -350,8 +352,9 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } - NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, getDisplayId(), - policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, + NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + getDisplayId(), policyFlags, + down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime); getListener()->notifyKey(&args); } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index 4c0b42a137..ca41712f48 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -86,7 +86,7 @@ private: bool isKeyboardOrGamepadKey(int32_t scanCode); bool isMediaKey(int32_t keyCode); - void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode); + void processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode, int32_t usageCode); bool updateMetaStateIfNeeded(int32_t keyCode, bool down); diff --git a/services/inputflinger/reader/mapper/LightInputMapper.h b/services/inputflinger/reader/mapper/LightInputMapper.h index 9254720385..43141b87c0 100644 --- a/services/inputflinger/reader/mapper/LightInputMapper.h +++ b/services/inputflinger/reader/mapper/LightInputMapper.h @@ -44,7 +44,7 @@ public: private: struct Light { - explicit Light(InputDeviceContext& context, std::string name, int32_t id, + explicit Light(InputDeviceContext& context, const std::string& name, int32_t id, InputDeviceLightType type) : context(context), name(name), id(id), type(type) {} virtual ~Light() {} @@ -65,7 +65,7 @@ private: }; struct SingleLight : public Light { - explicit SingleLight(InputDeviceContext& context, std::string name, int32_t id, + explicit SingleLight(InputDeviceContext& context, const std::string& name, int32_t id, int32_t rawId) : Light(context, name, id, InputDeviceLightType::SINGLE), rawId(rawId) {} int32_t rawId; @@ -77,7 +77,7 @@ private: struct RgbLight : public Light { explicit RgbLight(InputDeviceContext& context, int32_t id, - std::unordered_map<LightColor, int32_t> rawRgbIds, + const std::unordered_map<LightColor, int32_t>& rawRgbIds, std::optional<int32_t> rawGlobalId) : Light(context, "RGB", id, InputDeviceLightType::RGB), rawRgbIds(rawRgbIds), @@ -98,7 +98,7 @@ private: }; struct MultiColorLight : public Light { - explicit MultiColorLight(InputDeviceContext& context, std::string name, int32_t id, + explicit MultiColorLight(InputDeviceContext& context, const std::string& name, int32_t id, int32_t rawId) : Light(context, name, id, InputDeviceLightType::MULTI_COLOR), rawId(rawId) {} int32_t rawId; @@ -109,8 +109,8 @@ private: }; struct PlayerIdLight : public Light { - explicit PlayerIdLight(InputDeviceContext& context, std::string name, int32_t id, - std::unordered_map<int32_t, int32_t> rawLightIds) + explicit PlayerIdLight(InputDeviceContext& context, const std::string& name, int32_t id, + const std::unordered_map<int32_t, int32_t>& rawLightIds) : Light(context, name, id, InputDeviceLightType::PLAYER_ID), rawLightIds(rawLightIds) {} // Map from player Id to raw light Id @@ -132,4 +132,4 @@ private: } // namespace android -#endif // _UI_INPUTREADER_LIGHT_INPUT_MAPPER_H
\ No newline at end of file +#endif // _UI_INPUTREADER_LIGHT_INPUT_MAPPER_H diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp index 594ff42f87..e9d0189f1f 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp @@ -87,11 +87,11 @@ void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) { mRotaryEncoderScrollAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - sync(rawEvent->when); + sync(rawEvent->when, rawEvent->readTime); } } -void RotaryEncoderInputMapper::sync(nsecs_t when) { +void RotaryEncoderInputMapper::sync(nsecs_t when, nsecs_t readTime) { PointerCoords pointerCoords; pointerCoords.clear(); @@ -121,9 +121,9 @@ void RotaryEncoderInputMapper::sync(nsecs_t when) { int32_t metaState = getContext()->getGlobalMetaState(); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor); - NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, getDeviceId(), mSource, - displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, - metaState, /* buttonState */ 0, MotionClassification::NONE, + NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, readTime, getDeviceId(), + mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, + 0, metaState, /* buttonState */ 0, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {}); diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h index 7a77b1286c..e0c94040f0 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h @@ -42,7 +42,7 @@ private: float mScalingFactor; int32_t mOrientation; - void sync(nsecs_t when); + void sync(nsecs_t when, nsecs_t readTime); }; } // namespace android diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h index a86443dee1..5344227b0b 100644 --- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h +++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h @@ -59,27 +59,27 @@ static bool isPointerDown(int32_t buttonState) { } static void synthesizeButtonKey(InputReaderContext* context, int32_t action, nsecs_t when, - int32_t deviceId, uint32_t source, int32_t displayId, - uint32_t policyFlags, int32_t lastButtonState, + nsecs_t readTime, int32_t deviceId, uint32_t source, + int32_t displayId, uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState, int32_t buttonState, int32_t keyCode) { if ((action == AKEY_EVENT_ACTION_DOWN && !(lastButtonState & buttonState) && (currentButtonState & buttonState)) || (action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) && !(currentButtonState & buttonState))) { - NotifyKeyArgs args(context->getNextId(), when, deviceId, source, displayId, policyFlags, - action, 0, keyCode, 0, context->getGlobalMetaState(), when); + NotifyKeyArgs args(context->getNextId(), when, readTime, deviceId, source, displayId, + policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when); context->getListener()->notifyKey(&args); } } static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, nsecs_t when, - int32_t deviceId, uint32_t source, int32_t displayId, - uint32_t policyFlags, int32_t lastButtonState, + nsecs_t readTime, int32_t deviceId, uint32_t source, + int32_t displayId, uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) { - synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags, + synthesizeButtonKey(context, action, when, readTime, deviceId, source, displayId, policyFlags, lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK); - synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags, + synthesizeButtonKey(context, action, when, readTime, deviceId, source, displayId, policyFlags, lastButtonState, currentButtonState, AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD); } diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index d1df37b686..16cf010c6f 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -1016,7 +1016,8 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal; // Abort current pointer usages because the state has changed. - abortPointerUsage(when, 0 /*policyFlags*/); + const nsecs_t readTime = when; // synthetic event + abortPointerUsage(when, readTime, 0 /*policyFlags*/); } // Inform the dispatcher about the changes. @@ -1406,11 +1407,11 @@ void TouchInputMapper::process(const RawEvent* rawEvent) { mTouchButtonAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - sync(rawEvent->when); + sync(rawEvent->when, rawEvent->readTime); } } -void TouchInputMapper::sync(nsecs_t when) { +void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) { const RawState* last = mRawStatesPending.empty() ? &mCurrentRawState : &mRawStatesPending.back(); @@ -1420,6 +1421,7 @@ void TouchInputMapper::sync(nsecs_t when) { RawState* next = &mRawStatesPending.back(); next->clear(); next->when = when; + next->readTime = readTime; // Sync button state. next->buttonState = @@ -1453,7 +1455,7 @@ void TouchInputMapper::sync(nsecs_t when) { void TouchInputMapper::processRawTouches(bool timeout) { if (mDeviceMode == DeviceMode::DISABLED) { // Drop all input if the device is disabled. - cancelTouch(mCurrentRawState.when); + cancelTouch(mCurrentRawState.when, mCurrentRawState.readTime); mCurrentCookedState.clear(); updateTouchSpots(); return; @@ -1479,8 +1481,9 @@ void TouchInputMapper::processRawTouches(bool timeout) { mCurrentRawState.copyFrom(next); if (mCurrentRawState.when < mLastRawState.when) { mCurrentRawState.when = mLastRawState.when; + mCurrentRawState.readTime = mLastRawState.readTime; } - cookAndDispatch(mCurrentRawState.when); + cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime); } if (count != 0) { mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count); @@ -1494,7 +1497,8 @@ void TouchInputMapper::processRawTouches(bool timeout) { #if DEBUG_STYLUS_FUSION ALOGD("Timeout expired, synthesizing event with new stylus data"); #endif - cookAndDispatch(when); + const nsecs_t readTime = when; // consider this synthetic event to be zero latency + cookAndDispatch(when, readTime); } else if (mExternalStylusFusionTimeout == LLONG_MAX) { mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT; getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout); @@ -1502,7 +1506,7 @@ void TouchInputMapper::processRawTouches(bool timeout) { } } -void TouchInputMapper::cookAndDispatch(nsecs_t when) { +void TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t readTime) { // Always start with a clean state. mCurrentCookedState.clear(); @@ -1528,7 +1532,7 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { // Consume raw off-screen touches before cooking pointer data. // If touches are consumed, subsequent code will not receive any pointer data. - if (consumeRawTouches(when, policyFlags)) { + if (consumeRawTouches(when, readTime, policyFlags)) { mCurrentRawState.rawPointerData.clear(); } @@ -1541,8 +1545,8 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { applyExternalStylusTouchState(when); // Synthesize key down from raw buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource, - mViewport.displayId, policyFlags, mLastCookedState.buttonState, + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(), + mSource, mViewport.displayId, policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState); // Dispatch the touches either directly or by translation through a pointer on screen. @@ -1585,16 +1589,16 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { pointerUsage = PointerUsage::GESTURES; } - dispatchPointerUsage(when, policyFlags, pointerUsage); + dispatchPointerUsage(when, readTime, policyFlags, pointerUsage); } else { updateTouchSpots(); if (!mCurrentMotionAborted) { - dispatchButtonRelease(when, policyFlags); - dispatchHoverExit(when, policyFlags); - dispatchTouches(when, policyFlags); - dispatchHoverEnterAndMove(when, policyFlags); - dispatchButtonPress(when, policyFlags); + dispatchButtonRelease(when, readTime, policyFlags); + dispatchHoverExit(when, readTime, policyFlags); + dispatchTouches(when, readTime, policyFlags); + dispatchHoverEnterAndMove(when, readTime, policyFlags); + dispatchButtonPress(when, readTime, policyFlags); } if (mCurrentCookedState.cookedPointerData.pointerCount == 0) { @@ -1603,7 +1607,7 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { } // Synthesize key up from raw buttons if needed. - synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource, + synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(), mSource, mViewport.displayId, policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState); @@ -1716,7 +1720,9 @@ bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeou void TouchInputMapper::timeoutExpired(nsecs_t when) { if (mDeviceMode == DeviceMode::POINTER) { if (mPointerUsage == PointerUsage::GESTURES) { - dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/); + // Since this is a synthetic event, we can consider its latency to be zero + const nsecs_t readTime = when; + dispatchPointerGestures(when, readTime, 0 /*policyFlags*/, true /*isTimeout*/); } } else if (mDeviceMode == DeviceMode::DIRECT) { if (mExternalStylusFusionTimeout < when) { @@ -1738,7 +1744,7 @@ void TouchInputMapper::updateExternalStylusState(const StylusState& state) { } } -bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { +bool TouchInputMapper::consumeRawTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { // Check for release of a virtual key. if (mCurrentVirtualKey.down) { if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) { @@ -1749,7 +1755,7 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d", mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); #endif - dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_UP, + dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); } return true; @@ -1776,7 +1782,7 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d", mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); #endif - dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_UP, + dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY | AKEY_EVENT_FLAG_CANCELED); } @@ -1807,7 +1813,7 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d", mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode); #endif - dispatchVirtualKey(when, policyFlags, AKEY_EVENT_ACTION_DOWN, + dispatchVirtualKey(when, readTime, policyFlags, AKEY_EVENT_ACTION_DOWN, AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY); } @@ -1838,7 +1844,7 @@ bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) { return false; } -void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, +void TouchInputMapper::dispatchVirtualKey(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, int32_t keyEventAction, int32_t keyEventFlags) { int32_t keyCode = mCurrentVirtualKey.keyCode; int32_t scanCode = mCurrentVirtualKey.scanCode; @@ -1846,19 +1852,19 @@ void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, int32_t metaState = getContext()->getGlobalMetaState(); policyFlags |= POLICY_FLAG_VIRTUAL; - NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, - mViewport.displayId, policyFlags, keyEventAction, keyEventFlags, keyCode, - scanCode, metaState, downTime); + NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), + AINPUT_SOURCE_KEYBOARD, mViewport.displayId, policyFlags, keyEventAction, + keyEventFlags, keyCode, scanCode, metaState, downTime); getListener()->notifyKey(&args); } -void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::abortTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits; if (!currentIdBits.isEmpty()) { int32_t metaState = getContext()->getGlobalMetaState(); int32_t buttonState = mCurrentCookedState.buttonState; - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, - buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1, @@ -1867,7 +1873,7 @@ void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) { } } -void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits; BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits; int32_t metaState = getContext()->getGlobalMetaState(); @@ -1877,8 +1883,8 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { if (!currentIdBits.isEmpty()) { // No pointer id changes so this is a move event. // The listener takes care of batching moves so we don't have to deal with that here. - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, - buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1, @@ -1912,7 +1918,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { if (isCanceled) { ALOGI("Canceling pointer %d for the palm event was detected.", upId); } - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, isCanceled ? AMOTION_EVENT_FLAG_CANCELED : 0, metaState, buttonState, 0, mLastCookedState.cookedPointerData.pointerProperties, mLastCookedState.cookedPointerData.pointerCoords, @@ -1927,8 +1933,9 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { // events, they do not generally handle them except when presented in a move event. if (moveNeeded && !moveIdBits.isEmpty()) { ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value); - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, - buttonState, 0, mCurrentCookedState.cookedPointerData.pointerProperties, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, + metaState, buttonState, 0, + mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime); @@ -1944,8 +1951,8 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { mDownTime = when; } - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, - metaState, buttonState, 0, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, + 0, 0, metaState, buttonState, 0, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits, @@ -1954,13 +1961,13 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { } } -void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchHoverExit(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { if (mSentHoverEnter && (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty() || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) { int32_t metaState = getContext()->getGlobalMetaState(); - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, - mLastCookedState.buttonState, 0, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, + metaState, mLastCookedState.buttonState, 0, mLastCookedState.cookedPointerData.pointerProperties, mLastCookedState.cookedPointerData.pointerCoords, mLastCookedState.cookedPointerData.idToIndex, @@ -1970,13 +1977,14 @@ void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) { } } -void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, nsecs_t readTime, + uint32_t policyFlags) { if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty() && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) { int32_t metaState = getContext()->getGlobalMetaState(); if (!mSentHoverEnter) { - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, - metaState, mCurrentRawState.buttonState, 0, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER, + 0, 0, metaState, mCurrentRawState.buttonState, 0, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, @@ -1985,8 +1993,8 @@ void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFl mSentHoverEnter = true; } - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, - mCurrentRawState.buttonState, 0, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, + metaState, mCurrentRawState.buttonState, 0, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, @@ -1995,7 +2003,7 @@ void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFl } } -void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchButtonRelease(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState); const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData); const int32_t metaState = getContext()->getGlobalMetaState(); @@ -2003,7 +2011,7 @@ void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) while (!releasedButtons.isEmpty()) { int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit()); buttonState &= ~actionButton; - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_RELEASE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0, metaState, buttonState, 0, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, @@ -2012,7 +2020,7 @@ void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) } } -void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchButtonPress(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState); const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData); const int32_t metaState = getContext()->getGlobalMetaState(); @@ -2020,8 +2028,8 @@ void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) { while (!pressedButtons.isEmpty()) { int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit()); buttonState |= actionButton; - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, - 0, metaState, buttonState, 0, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, + actionButton, 0, metaState, buttonState, 0, mCurrentCookedState.cookedPointerData.pointerProperties, mCurrentCookedState.cookedPointerData.pointerCoords, mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1, @@ -2308,38 +2316,38 @@ void TouchInputMapper::cookPointerData() { } } -void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, +void TouchInputMapper::dispatchPointerUsage(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, PointerUsage pointerUsage) { if (pointerUsage != mPointerUsage) { - abortPointerUsage(when, policyFlags); + abortPointerUsage(when, readTime, policyFlags); mPointerUsage = pointerUsage; } switch (mPointerUsage) { case PointerUsage::GESTURES: - dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); + dispatchPointerGestures(when, readTime, policyFlags, false /*isTimeout*/); break; case PointerUsage::STYLUS: - dispatchPointerStylus(when, policyFlags); + dispatchPointerStylus(when, readTime, policyFlags); break; case PointerUsage::MOUSE: - dispatchPointerMouse(when, policyFlags); + dispatchPointerMouse(when, readTime, policyFlags); break; case PointerUsage::NONE: break; } } -void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::abortPointerUsage(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { switch (mPointerUsage) { case PointerUsage::GESTURES: - abortPointerGestures(when, policyFlags); + abortPointerGestures(when, readTime, policyFlags); break; case PointerUsage::STYLUS: - abortPointerStylus(when, policyFlags); + abortPointerStylus(when, readTime, policyFlags); break; case PointerUsage::MOUSE: - abortPointerMouse(when, policyFlags); + abortPointerMouse(when, readTime, policyFlags); break; case PointerUsage::NONE: break; @@ -2348,7 +2356,8 @@ void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) { mPointerUsage = PointerUsage::NONE; } -void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout) { +void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, + bool isTimeout) { // Update current gesture coordinates. bool cancelPreviousGesture, finishPreviousGesture; bool sendEvents = @@ -2441,8 +2450,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits); if (!dispatchedGestureIdBits.isEmpty()) { if (cancelPreviousGesture) { - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, - buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0, mPointerGesture.downTime); @@ -2459,9 +2468,9 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag while (!upGestureIdBits.isEmpty()) { uint32_t id = upGestureIdBits.clearFirstMarkedBit(); - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, - metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, - mPointerGesture.lastGestureProperties, + dispatchMotion(when, readTime, policyFlags, mSource, + AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, + AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, id, 0, 0, mPointerGesture.downTime); @@ -2473,8 +2482,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag // Send motion events for all pointers that moved. if (moveNeeded) { - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, - buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.currentGestureProperties, mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0, @@ -2493,8 +2502,9 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag mPointerGesture.downTime = when; } - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, - metaState, buttonState, 0, mPointerGesture.currentGestureProperties, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN, + 0, 0, metaState, buttonState, 0, + mPointerGesture.currentGestureProperties, mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, id, 0, 0, mPointerGesture.downTime); @@ -2503,8 +2513,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag // Send motion events for hover. if (mPointerGesture.currentGestureMode == PointerGesture::Mode::HOVER) { - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, - buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.currentGestureProperties, mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex, @@ -2528,11 +2538,11 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y); const int32_t displayId = mPointerController->getDisplayId(); - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, - buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, - 1, &pointerProperties, &pointerCoords, 0, 0, x, y, - mPointerGesture.downTime, /* videoFrames */ {}); + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, + metaState, buttonState, MotionClassification::NONE, + AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, + 0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {}); getListener()->notifyMotion(&args); } @@ -2554,13 +2564,13 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlag } } -void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::abortPointerGestures(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { // Cancel previously dispatches pointers. if (!mPointerGesture.lastGestureIdBits.isEmpty()) { int32_t metaState = getContext()->getGlobalMetaState(); int32_t buttonState = mCurrentRawState.buttonState; - dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, - buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, + dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, + metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1, 0, 0, mPointerGesture.downTime); @@ -3335,7 +3345,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi return true; } -void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { mPointerSimple.currentCoords.clear(); mPointerSimple.currentProperties.clear(); @@ -3363,14 +3373,14 @@ void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) hovering = false; } - dispatchPointerSimple(when, policyFlags, down, hovering); + dispatchPointerSimple(when, readTime, policyFlags, down, hovering); } -void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) { - abortPointerSimple(when, policyFlags); +void TouchInputMapper::abortPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { + abortPointerSimple(when, readTime, policyFlags); } -void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::dispatchPointerMouse(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { mPointerSimple.currentCoords.clear(); mPointerSimple.currentProperties.clear(); @@ -3417,17 +3427,17 @@ void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) hovering = false; } - dispatchPointerSimple(when, policyFlags, down, hovering); + dispatchPointerSimple(when, readTime, policyFlags, down, hovering); } -void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) { - abortPointerSimple(when, policyFlags); +void TouchInputMapper::abortPointerMouse(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { + abortPointerSimple(when, readTime, policyFlags); mPointerVelocityControl.reset(); } -void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down, - bool hovering) { +void TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, + bool down, bool hovering) { int32_t metaState = getContext()->getGlobalMetaState(); if (down || hovering) { @@ -3448,8 +3458,8 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.down = false; // Send up. - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, @@ -3462,9 +3472,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.hovering = false; // Send hover exit. - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, - mLastRawState.buttonState, MotionClassification::NONE, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, + metaState, mLastRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision, xCursorPosition, yCursorPosition, mPointerSimple.downTime, @@ -3478,7 +3488,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.downTime = when; // Send down. - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, @@ -3489,8 +3499,8 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } // Send move. - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, @@ -3504,7 +3514,7 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, mPointerSimple.hovering = true; // Send hover enter. - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, @@ -3515,9 +3525,9 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } // Send hover move. - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState, - mCurrentRawState.buttonState, MotionClassification::NONE, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, + metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords, mOrientedXPrecision, mOrientedYPrecision, xCursorPosition, yCursorPosition, @@ -3537,8 +3547,8 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll); pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll); - NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId, - policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, + displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties, &pointerCoords, mOrientedXPrecision, mOrientedYPrecision, @@ -3556,17 +3566,17 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, } } -void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) { +void TouchInputMapper::abortPointerSimple(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { mPointerSimple.currentCoords.clear(); mPointerSimple.currentProperties.clear(); - dispatchPointerSimple(when, policyFlags, false, false); + dispatchPointerSimple(when, readTime, policyFlags, false, false); } -void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, - int32_t action, int32_t actionButton, int32_t flags, - int32_t metaState, int32_t buttonState, int32_t edgeFlags, - const PointerProperties* properties, +void TouchInputMapper::dispatchMotion(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, + uint32_t source, int32_t action, int32_t actionButton, + int32_t flags, int32_t metaState, int32_t buttonState, + int32_t edgeFlags, const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { @@ -3615,8 +3625,8 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames(); std::for_each(frames.begin(), frames.end(), [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); }); - NotifyMotionArgs args(getContext()->getNextId(), when, deviceId, source, displayId, policyFlags, - action, actionButton, flags, metaState, buttonState, + NotifyMotionArgs args(getContext()->getNextId(), when, readTime, deviceId, source, displayId, + policyFlags, action, actionButton, flags, metaState, buttonState, MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition, downTime, std::move(frames)); @@ -3653,9 +3663,9 @@ bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties return changed; } -void TouchInputMapper::cancelTouch(nsecs_t when) { - abortPointerUsage(when, 0 /*policyFlags*/); - abortTouches(when, 0 /* policyFlags*/); +void TouchInputMapper::cancelTouch(nsecs_t when, nsecs_t readTime) { + abortPointerUsage(when, readTime, 0 /*policyFlags*/); + abortTouches(when, readTime, 0 /* policyFlags*/); } // Transform raw coordinate to surface coordinate diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index 66218251f9..cb52e2d774 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -150,7 +150,7 @@ public: bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) override; - void cancelTouch(nsecs_t when) override; + void cancelTouch(nsecs_t when, nsecs_t readTime) override; void timeoutExpired(nsecs_t when) override; void updateExternalStylusState(const StylusState& state) override; std::optional<int32_t> getAssociatedDisplayId() override; @@ -298,6 +298,7 @@ protected: struct RawState { nsecs_t when; + nsecs_t readTime; // Raw pointer sample data. RawPointerData rawPointerData; @@ -310,6 +311,7 @@ protected: void copyFrom(const RawState& other) { when = other.when; + readTime = other.readTime; rawPointerData.copyFrom(other.rawPointerData); buttonState = other.buttonState; rawVScroll = other.rawVScroll; @@ -318,6 +320,7 @@ protected: void clear() { when = 0; + readTime = 0; rawPointerData.clear(); buttonState = 0; rawVScroll = 0; @@ -702,39 +705,42 @@ private: void resetExternalStylus(); void clearStylusDataPendingFlags(); - void sync(nsecs_t when); + void sync(nsecs_t when, nsecs_t readTime); - bool consumeRawTouches(nsecs_t when, uint32_t policyFlags); + bool consumeRawTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); void processRawTouches(bool timeout); - void cookAndDispatch(nsecs_t when); - void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags, int32_t keyEventAction, - int32_t keyEventFlags); - - void dispatchTouches(nsecs_t when, uint32_t policyFlags); - void dispatchHoverExit(nsecs_t when, uint32_t policyFlags); - void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags); - void dispatchButtonRelease(nsecs_t when, uint32_t policyFlags); - void dispatchButtonPress(nsecs_t when, uint32_t policyFlags); + void cookAndDispatch(nsecs_t when, nsecs_t readTime); + void dispatchVirtualKey(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, + int32_t keyEventAction, int32_t keyEventFlags); + + void dispatchTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); + void dispatchHoverExit(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); + void dispatchHoverEnterAndMove(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); + void dispatchButtonRelease(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); + void dispatchButtonPress(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData); void cookPointerData(); - void abortTouches(nsecs_t when, uint32_t policyFlags); + void abortTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); - void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage); - void abortPointerUsage(nsecs_t when, uint32_t policyFlags); + void dispatchPointerUsage(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, + PointerUsage pointerUsage); + void abortPointerUsage(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); - void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout); - void abortPointerGestures(nsecs_t when, uint32_t policyFlags); + void dispatchPointerGestures(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, + bool isTimeout); + void abortPointerGestures(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); bool preparePointerGestures(nsecs_t when, bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout); - void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags); - void abortPointerStylus(nsecs_t when, uint32_t policyFlags); + void dispatchPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); + void abortPointerStylus(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); - void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags); - void abortPointerMouse(nsecs_t when, uint32_t policyFlags); + void dispatchPointerMouse(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); + void abortPointerMouse(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); - void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags, bool down, bool hovering); - void abortPointerSimple(nsecs_t when, uint32_t policyFlags); + void dispatchPointerSimple(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, bool down, + bool hovering); + void abortPointerSimple(nsecs_t when, nsecs_t readTime, uint32_t policyFlags); bool assignExternalStylusId(const RawState& state, bool timeout); void applyExternalStylusButtonState(nsecs_t when); @@ -744,9 +750,9 @@ private: // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the // method will take care of setting the index and transmuting the action to DOWN or UP // it is the first / last pointer to go down / up. - void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action, - int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, - int32_t edgeFlags, const PointerProperties* properties, + void dispatchMotion(nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source, + int32_t action, int32_t actionButton, int32_t flags, int32_t metaState, + int32_t buttonState, int32_t edgeFlags, const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime); diff --git a/services/inputflinger/tests/InputClassifierConverter_test.cpp b/services/inputflinger/tests/InputClassifierConverter_test.cpp index f58b6281df..c0ada9d517 100644 --- a/services/inputflinger/tests/InputClassifierConverter_test.cpp +++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp @@ -38,13 +38,13 @@ static NotifyMotionArgs generateBasicMotionArgs() { coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 2); coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.5); static constexpr nsecs_t downTime = 2; - NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 3 /*deviceId*/, - AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4 /*policyFlags*/, - AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, 0 /*flags*/, - AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE, - AMOTION_EVENT_EDGE_FLAG_NONE, 1 /*pointerCount*/, &properties, - &coords, 0 /*xPrecision*/, 0 /*yPrecision*/, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 2 /*readTime*/, + 3 /*deviceId*/, AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, + 4 /*policyFlags*/, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, + 0 /*flags*/, AMETA_NONE, 0 /*buttonState*/, + MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, + 1 /*pointerCount*/, &properties, &coords, 0 /*xPrecision*/, + 0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime, {} /*videoFrames*/); return motionArgs; diff --git a/services/inputflinger/tests/InputClassifier_test.cpp b/services/inputflinger/tests/InputClassifier_test.cpp index ab74a0498d..a72df01ce6 100644 --- a/services/inputflinger/tests/InputClassifier_test.cpp +++ b/services/inputflinger/tests/InputClassifier_test.cpp @@ -41,13 +41,13 @@ static NotifyMotionArgs generateBasicMotionArgs() { coords.setAxisValue(AMOTION_EVENT_AXIS_X, 1); coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1); static constexpr nsecs_t downTime = 2; - NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 3 /*deviceId*/, - AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4 /*policyFlags*/, - AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, 0 /*flags*/, - AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE, - AMOTION_EVENT_EDGE_FLAG_NONE, 1 /*pointerCount*/, &properties, - &coords, 0 /*xPrecision*/, 0 /*yPrecision*/, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + NotifyMotionArgs motionArgs(1 /*sequenceNum*/, downTime /*eventTime*/, 2 /*readTime*/, + 3 /*deviceId*/, AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, + 4 /*policyFlags*/, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, + 0 /*flags*/, AMETA_NONE, 0 /*buttonState*/, + MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, + 1 /*pointerCount*/, &properties, &coords, 0 /*xPrecision*/, + 0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime, {} /*videoFrames*/); return motionArgs; @@ -85,9 +85,10 @@ TEST_F(InputClassifierTest, SendToNextStage_NotifyConfigurationChangedArgs) { TEST_F(InputClassifierTest, SendToNextStage_NotifyKeyArgs) { // Create a basic key event and send to classifier - NotifyKeyArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*deviceId*/, AINPUT_SOURCE_KEYBOARD, - ADISPLAY_ID_DEFAULT, 0/*policyFlags*/, AKEY_EVENT_ACTION_DOWN, 4/*flags*/, - AKEYCODE_HOME, 5/*scanCode*/, AMETA_NONE, 6/*downTime*/); + NotifyKeyArgs args(1 /*sequenceNum*/, 2 /*eventTime*/, 21 /*readTime*/, 3 /*deviceId*/, + AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, 0 /*policyFlags*/, + AKEY_EVENT_ACTION_DOWN, 4 /*flags*/, AKEYCODE_HOME, 5 /*scanCode*/, + AMETA_NONE, 6 /*downTime*/); mClassifier->notifyKey(&args); NotifyKeyArgs outArgs; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 8456387b58..e027c5e376 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -377,7 +377,7 @@ private: mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask); } - void pokeUserActivity(nsecs_t, int32_t) override {} + void pokeUserActivity(nsecs_t, int32_t, int32_t) override {} bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; } @@ -1234,9 +1234,9 @@ static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispa static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) { nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid key event. - NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, - POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A, - AMETA_NONE, currentTime); + NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, + displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, + KEY_A, AMETA_NONE, currentTime); return args; } @@ -1263,7 +1263,7 @@ static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid motion event. - NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId, + NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId, POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties, diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 2836516a41..d69bb6a303 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -50,7 +50,8 @@ using namespace android::flag_operators; static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms; // An arbitrary time value. -static const nsecs_t ARBITRARY_TIME = 1234; +static constexpr nsecs_t ARBITRARY_TIME = 1234; +static constexpr nsecs_t READ_TIME = 4321; // Arbitrary display properties. static constexpr int32_t DISPLAY_ID = 0; @@ -442,14 +443,14 @@ public: device->identifier.name = name; mDevices.add(deviceId, device); - enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0); + enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0); } void removeDevice(int32_t deviceId) { delete mDevices.valueFor(deviceId); mDevices.removeItem(deviceId); - enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0); + enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0); } bool isDeviceEnabled(int32_t deviceId) { @@ -490,7 +491,7 @@ public: } void finishDeviceScan() { - enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0); + enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0); } void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) { @@ -604,11 +605,12 @@ public: device->virtualKeys.push_back(definition); } - void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type, - int32_t code, int32_t value) { + void enqueueEvent(nsecs_t when, nsecs_t readTime, int32_t deviceId, int32_t type, int32_t code, + int32_t value) { std::scoped_lock<std::mutex> lock(mLock); RawEvent event; event.when = when; + event.readTime = readTime; event.deviceId = deviceId; event.type = type; event.code = code; @@ -1774,18 +1776,21 @@ TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChange TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { constexpr int32_t deviceId = END_RESERVED_ID + 1000; constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD; + constexpr nsecs_t when = 0; constexpr int32_t eventHubId = 1; + constexpr nsecs_t readTime = 2; FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass, AINPUT_SOURCE_KEYBOARD, nullptr); - mFakeEventHub->enqueueEvent(0, eventHubId, EV_KEY, KEY_A, 1); + mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1); mReader->loopOnce(); ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty()); RawEvent event; ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event)); - ASSERT_EQ(0, event.when); + ASSERT_EQ(when, event.when); + ASSERT_EQ(readTime, event.readTime); ASSERT_EQ(eventHubId, event.deviceId); ASSERT_EQ(EV_KEY, event.type); ASSERT_EQ(KEY_A, event.code); @@ -2193,12 +2198,14 @@ TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) { ASSERT_NE(prevId, keyArgs.id); prevId = keyArgs.id; ASSERT_LE(prevTimestamp, keyArgs.eventTime); + ASSERT_LE(keyArgs.eventTime, keyArgs.readTime); prevTimestamp = keyArgs.eventTime; ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action); ASSERT_NE(prevId, keyArgs.id); ASSERT_LE(prevTimestamp, keyArgs.eventTime); + ASSERT_LE(keyArgs.eventTime, keyArgs.readTime); } /** @@ -2675,9 +2682,11 @@ protected: mFakePolicy->clearViewports(); } - void process(InputMapper& mapper, nsecs_t when, int32_t type, int32_t code, int32_t value) { + void process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type, int32_t code, + int32_t value) { RawEvent event; event.when = when; + event.readTime = readTime; event.deviceId = mapper.getDeviceContext().getEventHubId(); event.type = type; event.code = code; @@ -2756,10 +2765,10 @@ TEST_F(SwitchInputMapperTest, GetSwitchState) { TEST_F(SwitchInputMapperTest, Process) { SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>(); - process(mapper, ARBITRARY_TIME, EV_SW, SW_LID, 1); - process(mapper, ARBITRARY_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1); - process(mapper, ARBITRARY_TIME, EV_SW, SW_HEADPHONE_INSERT, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_HEADPHONE_INSERT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); NotifySwitchArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args)); @@ -2929,11 +2938,11 @@ TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) { std::chrono::microseconds(10000), std::chrono::microseconds(0))); ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID)); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, 20000); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, -20000); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Z, 40000); - process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); NotifySensorArgs args; std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, @@ -2959,11 +2968,11 @@ TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) { std::chrono::microseconds(10000), std::chrono::microseconds(0))); ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID)); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RX, 20000); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RY, -20000); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RZ, 40000); - process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); NotifySensorArgs args; std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, @@ -3154,14 +3163,14 @@ void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t rotatedKeyCode, int32_t displayId) { NotifyKeyArgs args; - process(mapper, ARBITRARY_TIME, EV_KEY, originalScanCode, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); ASSERT_EQ(originalScanCode, args.scanCode); ASSERT_EQ(rotatedKeyCode, args.keyCode); ASSERT_EQ(displayId, args.displayId); - process(mapper, ARBITRARY_TIME, EV_KEY, originalScanCode, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); ASSERT_EQ(originalScanCode, args.scanCode); @@ -3194,7 +3203,7 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { mapper.updateMetaState(AKEYCODE_NUM_LOCK); // Key down by scan code. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1); NotifyKeyArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -3209,7 +3218,7 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Key up by scan code. - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_HOME, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -3223,8 +3232,8 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Key down by usage code. - process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_A); - process(mapper, ARBITRARY_TIME, EV_KEY, 0, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -3238,8 +3247,8 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Key up by usage code. - process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_A); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, 0, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -3253,8 +3262,8 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Key down with unknown scan code or usage code. - process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UNKNOWN, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -3268,8 +3277,8 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Key up with unknown scan code or usage code. - process(mapper, ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_UNKNOWN, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -3283,6 +3292,28 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); } +/** + * Ensure that the readTime is set to the time when the EV_KEY is received. + */ +TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) { + mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); + + KeyboardInputMapper& mapper = + addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + NotifyKeyArgs args; + + // Key down + process(mapper, ARBITRARY_TIME, 12 /*readTime*/, EV_KEY, KEY_HOME, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(12, args.readTime); + + // Key up + process(mapper, ARBITRARY_TIME, 15 /*readTime*/, EV_KEY, KEY_HOME, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(15, args.readTime); +} + TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0); mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0); @@ -3299,7 +3330,7 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { mapper.updateMetaState(AKEYCODE_NUM_LOCK); // Metakey down. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_LEFTSHIFT, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1); NotifyKeyArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); @@ -3307,19 +3338,19 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled()); // Key down. - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_A, 1); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState()); // Key up. - process(mapper, ARBITRARY_TIME + 2, EV_KEY, KEY_A, 0); + process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState()); // Metakey up. - process(mapper, ARBITRARY_TIME + 3, EV_KEY, KEY_LEFTSHIFT, 0); + process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_NONE, args.metaState); ASSERT_EQ(AMETA_NONE, mapper.getMetaState()); @@ -3406,7 +3437,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { NotifyKeyArgs args; clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_270); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); ASSERT_EQ(KEY_UP, args.scanCode); @@ -3414,7 +3445,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { clearViewports(); prepareDisplay(DISPLAY_ORIENTATION_180); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); ASSERT_EQ(KEY_UP, args.scanCode); @@ -3432,16 +3463,16 @@ TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware NotifyKeyArgs args; // Display id should be ADISPLAY_ID_NONE without any display configuration. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId); prepareDisplay(DISPLAY_ORIENTATION_0); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId); } @@ -3462,9 +3493,9 @@ TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) { setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DISPLAY_ID, args.displayId); @@ -3472,9 +3503,9 @@ TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) { clearViewports(); setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(newDisplayId, args.displayId); } @@ -3538,48 +3569,48 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); // Toggle caps lock on. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState()); // Toggle num lock on. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState()); // Toggle caps lock off. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState()); // Toggle scroll lock on. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState()); // Toggle num lock off. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState()); // Toggle scroll lock off. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); @@ -3607,7 +3638,7 @@ TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) { NotifyKeyArgs args; // Press button "A" - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_A, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_NONE, args.metaState); ASSERT_EQ(AMETA_NONE, mapper.getMetaState()); @@ -3615,7 +3646,7 @@ TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) { ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode); // Button up. - process(mapper, ARBITRARY_TIME + 2, EV_KEY, BTN_A, 0); + process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_NONE, args.metaState); ASSERT_EQ(AMETA_NONE, mapper.getMetaState()); @@ -3722,20 +3753,20 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) { ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); // Toggle caps lock on. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL)); ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState()); // Toggle num lock on. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML)); ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState()); // Toggle scroll lock on. - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL)); ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState()); @@ -3790,28 +3821,28 @@ TEST_F(KeyboardInputMapperTest_ExternalDevice, WakeBehavior) { addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1); NotifyKeyArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_HOME, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(uint32_t(0), args.policyFlags); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_PLAY, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(uint32_t(0), args.policyFlags); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_PLAY, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(uint32_t(0), args.policyFlags); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_PLAYPAUSE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_PLAYPAUSE, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); } @@ -3828,28 +3859,28 @@ TEST_F(KeyboardInputMapperTest_ExternalDevice, DoNotWakeByDefaultBehavior) { addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1); NotifyKeyArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_HOME, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_DOWN, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(uint32_t(0), args.policyFlags); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_DOWN, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(uint32_t(0), args.policyFlags); - process(mapper, ARBITRARY_TIME, EV_KEY, KEY_PLAY, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); - process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_PLAY, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); } @@ -3887,9 +3918,9 @@ void CursorInputMapperTest::testMotionRotation(CursorInputMapper& mapper, int32_ int32_t rotatedY) { NotifyMotionArgs args; - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, originalX); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, originalY); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, originalX); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, originalY); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -3970,8 +4001,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat // Button press. // Mostly testing non x/y behavior here so we don't need to check again elsewhere. - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -4011,8 +4042,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Button release. Should have same down time. - process(mapper, ARBITRARY_TIME + 1, EV_KEY, BTN_MOUSE, 0); - process(mapper, ARBITRARY_TIME + 1, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -4059,16 +4090,16 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { NotifyMotionArgs args; // Motion in X but not Y. - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Motion in Y but not X. - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, -2); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, -2); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -4082,8 +4113,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { NotifyMotionArgs args; // Button press. - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -4095,8 +4126,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Button release. - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -4115,10 +4146,10 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { NotifyMotionArgs args; // Combined X, Y and Button. - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 1); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, -2); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, -2); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -4132,9 +4163,9 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Move X, Y a bit while pressed. - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 2); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 2); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -4142,8 +4173,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Release Button. - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -4228,8 +4259,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { NotifyKeyArgs keyArgs; // press BTN_LEFT, release BTN_LEFT - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_LEFT, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_LEFT, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState); @@ -4244,8 +4275,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_LEFT, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_LEFT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(0, motionArgs.buttonState); @@ -4268,9 +4299,9 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 1); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_RIGHT, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MIDDLE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY, @@ -4297,8 +4328,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_RIGHT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); @@ -4313,16 +4344,16 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MIDDLE, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MIDDLE, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); @@ -4339,8 +4370,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // press BTN_BACK, release BTN_BACK - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_BACK, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_BACK, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); @@ -4359,8 +4390,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_BACK, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_BACK, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(0, motionArgs.buttonState); @@ -4380,8 +4411,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); // press BTN_SIDE, release BTN_SIDE - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_SIDE, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_SIDE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); @@ -4400,8 +4431,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_SIDE, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_SIDE, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(0, motionArgs.buttonState); @@ -4421,8 +4452,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); // press BTN_FORWARD, release BTN_FORWARD - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_FORWARD, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_FORWARD, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); @@ -4441,8 +4472,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_FORWARD, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_FORWARD, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(0, motionArgs.buttonState); @@ -4462,8 +4493,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); // press BTN_EXTRA, release BTN_EXTRA - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_EXTRA, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_EXTRA, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); @@ -4482,8 +4513,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_EXTRA, 0); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_EXTRA, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action); ASSERT_EQ(0, motionArgs.buttonState); @@ -4513,9 +4544,9 @@ TEST_F(CursorInputMapperTest, Process_WhenModeIsPointer_ShouldMoveThePointerArou NotifyMotionArgs args; - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action); @@ -4541,9 +4572,9 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { NotifyMotionArgs args; // Move. - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); @@ -4552,8 +4583,8 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 100.0f, 200.0f)); // Button press. - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); @@ -4566,8 +4597,8 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Button release. - process(mapper, ARBITRARY_TIME + 2, EV_KEY, BTN_MOUSE, 0); - process(mapper, ARBITRARY_TIME + 2, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action); @@ -4580,9 +4611,9 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Another move. - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 30); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 40); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 30); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 40); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE_RELATIVE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); @@ -4601,9 +4632,9 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime); ASSERT_EQ(DEVICE_ID, resetArgs.deviceId); - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action); @@ -4629,9 +4660,9 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) { mFakePointerController->setButtonState(0); NotifyMotionArgs args; - process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10); - process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20); - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source); ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action); @@ -4854,46 +4885,46 @@ void SingleTouchInputMapperTest::prepareAxes(int axes) { } void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y) { - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, x); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, y); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y); } void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, x); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, y); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y); } void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) { - process(mapper, ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0); } void SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper, int32_t pressure) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_PRESSURE, pressure); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure); } void SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor); } void SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper, int32_t distance) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_DISTANCE, distance); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance); } void SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_TILT_X, tiltX); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_TILT_Y, tiltY); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY); } void SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value) { - process(mapper, ARBITRARY_TIME, EV_KEY, code, value); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value); } void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) { - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); } TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) { @@ -6181,64 +6212,64 @@ void MultiTouchInputMapperTest::prepareAxes(int axes) { void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, x); - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, y); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y); } void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor); } void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor); } void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor); } void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor); } void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper, int32_t orientation) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation); } void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_PRESSURE, pressure); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure); } void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_DISTANCE, distance); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance); } void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, id); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id); } void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, slot); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot); } void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) { - process(mapper, ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType); } void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value) { - process(mapper, ARBITRARY_TIME, EV_KEY, code, value); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value); } void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) { - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_MT_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0); } void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper) { - process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); } TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) { @@ -7672,6 +7703,32 @@ TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) { } /** + * Ensure that the readTime is set to the SYN_REPORT value when processing touch events. + */ +TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareAxes(POSITION); + MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + + prepareDisplay(DISPLAY_ORIENTATION_0); + process(mapper, 10, 11 /*readTime*/, EV_ABS, ABS_MT_TRACKING_ID, 1); + process(mapper, 15, 16 /*readTime*/, EV_ABS, ABS_MT_POSITION_X, 100); + process(mapper, 20, 21 /*readTime*/, EV_ABS, ABS_MT_POSITION_Y, 100); + process(mapper, 25, 26 /*readTime*/, EV_SYN, SYN_REPORT, 0); + + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(26, args.readTime); + + process(mapper, 30, 31 /*readTime*/, EV_ABS, ABS_MT_POSITION_X, 110); + process(mapper, 30, 32 /*readTime*/, EV_ABS, ABS_MT_POSITION_Y, 220); + process(mapper, 30, 33 /*readTime*/, EV_SYN, SYN_REPORT, 0); + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(33, args.readTime); +} + +/** * When the viewport is not active (isActive=false), the touch mapper should be disabled and the * events should not be delivered to the listener. */ diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp index ad93a653a3..a489253207 100644 --- a/services/powermanager/benchmarks/Android.bp +++ b/services/powermanager/benchmarks/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_benchmark { name: "libpowermanager_benchmarks", srcs: [ diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp index 0f5037e7fb..69e4041aaa 100644 --- a/services/powermanager/tests/Android.bp +++ b/services/powermanager/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libpowermanager_test", test_suites: ["device-tests"], diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 625f315b00..470059ad02 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -154,6 +154,7 @@ filegroup { "DisplayRenderArea.cpp", "Effects/Daltonizer.cpp", "EventLog/EventLog.cpp", + "FpsReporter.cpp", "FrameTracer/FrameTracer.cpp", "FrameTracker.cpp", "Layer.cpp", diff --git a/services/surfaceflinger/FpsReporter.cpp b/services/surfaceflinger/FpsReporter.cpp new file mode 100644 index 0000000000..c7dbf88d32 --- /dev/null +++ b/services/surfaceflinger/FpsReporter.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2021 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 "FpsReporter" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "FpsReporter.h" + +#include "Layer.h" + +namespace android { + +FpsReporter::FpsReporter(frametimeline::FrameTimeline& frameTimeline) + : mFrameTimeline(frameTimeline) {} + +void FpsReporter::dispatchLayerFps() const { + std::vector<TrackedListener> localListeners; + { + std::scoped_lock lock(mMutex); + if (mListeners.empty()) { + return; + } + + std::transform(mListeners.begin(), mListeners.end(), std::back_inserter(localListeners), + [](const std::pair<wp<IBinder>, TrackedListener>& entry) { + return entry.second; + }); + } + + for (const auto& listener : localListeners) { + sp<Layer> promotedLayer = listener.layer.promote(); + if (promotedLayer != nullptr) { + std::unordered_set<int32_t> layerIds; + + promotedLayer->traverse(LayerVector::StateSet::Drawing, + [&](Layer* layer) { layerIds.insert(layer->getSequence()); }); + + listener.listener->onFpsReported(mFrameTimeline.computeFps(layerIds)); + } + } +} + +void FpsReporter::binderDied(const wp<IBinder>& who) { + std::scoped_lock lock(mMutex); + mListeners.erase(who); +} + +void FpsReporter::addListener(const sp<gui::IFpsListener>& listener, const wp<Layer>& layer) { + sp<IBinder> asBinder = IInterface::asBinder(listener); + asBinder->linkToDeath(this); + std::lock_guard lock(mMutex); + mListeners.emplace(wp<IBinder>(asBinder), TrackedListener{listener, layer}); +} + +void FpsReporter::removeListener(const sp<gui::IFpsListener>& listener) { + std::lock_guard lock(mMutex); + mListeners.erase(wp<IBinder>(IInterface::asBinder(listener))); +} + +} // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/FpsReporter.h b/services/surfaceflinger/FpsReporter.h new file mode 100644 index 0000000000..d64b3dc6cf --- /dev/null +++ b/services/surfaceflinger/FpsReporter.h @@ -0,0 +1,65 @@ +/* + * Copyright 2021 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 <android-base/thread_annotations.h> +#include <android/gui/IFpsListener.h> +#include <binder/IBinder.h> + +#include <unordered_map> + +#include "FrameTimeline/FrameTimeline.h" + +namespace android { + +class Layer; + +class FpsReporter : public IBinder::DeathRecipient { +public: + FpsReporter(frametimeline::FrameTimeline& frameTimeline); + + // Dispatches updated layer fps values for the registered listeners + // This method promotes Layer weak pointers and performs layer stack traversals, so mStateLock + // must be held when calling this method. + void dispatchLayerFps() const EXCLUDES(mMutex); + + // Override for IBinder::DeathRecipient + void binderDied(const wp<IBinder>&) override; + + // Registers an Fps listener that listens to fps updates for the provided layer + void addListener(const sp<gui::IFpsListener>& listener, const wp<Layer>& layer); + // Deregisters an Fps listener + void removeListener(const sp<gui::IFpsListener>& listener); + +private: + mutable std::mutex mMutex; + struct WpHash { + size_t operator()(const wp<IBinder>& p) const { + return std::hash<IBinder*>()(p.unsafe_get()); + } + }; + + struct TrackedListener { + sp<gui::IFpsListener> listener; + wp<Layer> layer; + }; + + frametimeline::FrameTimeline& mFrameTimeline; + std::unordered_map<wp<IBinder>, TrackedListener, WpHash> mListeners GUARDED_BY(mMutex); +}; + +} // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/FrameTimeline/Android.bp b/services/surfaceflinger/FrameTimeline/Android.bp index 1e6d21efe7..10a58333f9 100644 --- a/services/surfaceflinger/FrameTimeline/Android.bp +++ b/services/surfaceflinger/FrameTimeline/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libframetimeline", defaults: ["surfaceflinger_defaults"], diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index da04202ef2..ff000c9721 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -19,12 +19,15 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "FrameTimeline.h" + #include <android-base/stringprintf.h> #include <utils/Log.h> #include <utils/Trace.h> + #include <chrono> #include <cinttypes> #include <numeric> +#include <unordered_set> namespace android::frametimeline { @@ -277,8 +280,8 @@ int64_t TraceCookieCounter::getCookieForTracing() { } SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, - uid_t ownerUid, std::string layerName, std::string debugName, - PredictionState predictionState, + uid_t ownerUid, int32_t layerId, std::string layerName, + std::string debugName, PredictionState predictionState, frametimeline::TimelineItem&& predictions, std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds, @@ -289,6 +292,7 @@ SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t own mOwnerUid(ownerUid), mLayerName(std::move(layerName)), mDebugName(std::move(debugName)), + mLayerId(layerId), mPresentState(PresentState::Unknown), mPredictionState(predictionState), mPredictions(predictions), @@ -397,6 +401,8 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t StringAppendF(&result, "Scheduled rendering rate: %d fps\n", mRenderRate ? mRenderRate->getIntValue() : 0); StringAppendF(&result, "%s", indent.c_str()); + StringAppendF(&result, "Layer ID : %d\n", mLayerId); + StringAppendF(&result, "%s", indent.c_str()); StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str()); StringAppendF(&result, "%s", indent.c_str()); if (mPresentState == PresentState::Dropped) { @@ -458,7 +464,9 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime; const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime; - const nsecs_t deltaToVsync = std::abs(presentDelta) % refreshRate.getPeriodNsecs(); + const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0 + ? std::abs(presentDelta) % refreshRate.getPeriodNsecs() + : 0; if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) { mFrameReadyMetadata = FrameReadyMetadata::LateFinish; @@ -698,11 +706,11 @@ void FrameTimeline::registerDataSource() { } std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken( - const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId, std::string layerName, std::string debugName) { ATRACE_CALL(); if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { - return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, + return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId, std::move(layerName), std::move(debugName), PredictionState::None, TimelineItem(), mTimeStats, mJankClassificationThresholds, &mTraceCookieCounter); @@ -710,13 +718,13 @@ std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken( std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId); if (predictions) { - return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, + return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId, std::move(layerName), std::move(debugName), PredictionState::Valid, std::move(*predictions), mTimeStats, mJankClassificationThresholds, &mTraceCookieCounter); } - return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, + return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId, std::move(layerName), std::move(debugName), PredictionState::Expired, TimelineItem(), mTimeStats, mJankClassificationThresholds, &mTraceCookieCounter); @@ -804,7 +812,9 @@ void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) { // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there // was a prediction error or not. - nsecs_t deltaToVsync = std::abs(presentDelta) % mRefreshRate.getPeriodNsecs(); + nsecs_t deltaToVsync = mRefreshRate.getPeriodNsecs() > 0 + ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs() + : 0; if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) { mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent : FramePresentMetadata::EarlyPresent; @@ -968,6 +978,65 @@ void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const { } } +float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) { + if (layerIds.empty()) { + return 0.0f; + } + + std::vector<nsecs_t> presentTimes; + { + std::scoped_lock lock(mMutex); + presentTimes.reserve(mDisplayFrames.size()); + for (size_t i = 0; i < mDisplayFrames.size(); i++) { + const auto& displayFrame = mDisplayFrames[i]; + if (displayFrame->getActuals().presentTime <= 0) { + continue; + } + for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) { + if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented && + layerIds.count(surfaceFrame->getLayerId()) > 0) { + // We're looking for DisplayFrames that presents at least one layer from + // layerIds, so push the present time and skip looking through the rest of the + // SurfaceFrames. + presentTimes.push_back(displayFrame->getActuals().presentTime); + break; + } + } + } + } + + // FPS can't be computed when there's fewer than 2 presented frames. + if (presentTimes.size() <= 1) { + return 0.0f; + } + + nsecs_t priorPresentTime = -1; + nsecs_t totalPresentToPresentWalls = 0; + + for (const nsecs_t presentTime : presentTimes) { + if (priorPresentTime == -1) { + priorPresentTime = presentTime; + continue; + } + + totalPresentToPresentWalls += (presentTime - priorPresentTime); + priorPresentTime = presentTime; + } + + if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) { + ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64, + totalPresentToPresentWalls); + return 0.0f; + } + + const constexpr nsecs_t kOneSecond = + std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count(); + // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) = + // M frames / second + return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) / + static_cast<float>(totalPresentToPresentWalls); +} + void FrameTimeline::flushPendingPresentFences() { for (size_t i = 0; i < mPendingPresentFences.size(); i++) { const auto& pendingPresentFence = mPendingPresentFences[i]; diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index 8f3157d80c..d65769b8f4 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -156,9 +156,10 @@ public: // Only FrameTimeline can construct a SurfaceFrame as it provides Predictions(through // TokenManager), Thresholds and TimeStats pointer. SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, - std::string layerName, std::string debugName, PredictionState predictionState, - TimelineItem&& predictions, std::shared_ptr<TimeStats> timeStats, - JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter); + int32_t layerId, std::string layerName, std::string debugName, + PredictionState predictionState, TimelineItem&& predictions, + std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds, + TraceCookieCounter* traceCookieCounter); ~SurfaceFrame() = default; // Returns std::nullopt if the frame hasn't been classified yet. @@ -199,6 +200,7 @@ public: // Getter functions used only by FrameTimelineTests and SurfaceFrame internally TimelineItem getActuals() const; pid_t getOwnerPid() const { return mOwnerPid; }; + int32_t getLayerId() const { return mLayerId; }; PredictionState getPredictionState() const; PresentState getPresentState() const; FrameReadyMetadata getFrameReadyMetadata() const; @@ -221,6 +223,7 @@ private: const uid_t mOwnerUid; const std::string mLayerName; const std::string mDebugName; + const int32_t mLayerId; PresentState mPresentState GUARDED_BY(mMutex); const PredictionState mPredictionState; const TimelineItem mPredictions; @@ -267,7 +270,7 @@ public: // Debug name is the human-readable debugging string for dumpsys. virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken( const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, - std::string layerName, std::string debugName) = 0; + int32_t layerId, std::string layerName, std::string debugName) = 0; // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be // composited into one display frame. @@ -292,6 +295,11 @@ public: // Sets the max number of display frames that can be stored. Called by SF backdoor. virtual void setMaxDisplayFrames(uint32_t size); + // Computes the historical fps for the provided set of layer IDs + // The fps is compted from the linear timeline of present timestamps for DisplayFrames + // containing at least one layer ID. + virtual float computeFps(const std::unordered_set<int32_t>& layerIds); + // Restores the max number of display frames to default. Called by SF backdoor. virtual void reset() = 0; }; @@ -417,13 +425,14 @@ public: frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; } std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken( const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, - std::string layerName, std::string debugName) override; + int32_t layerId, std::string layerName, std::string debugName) override; void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) override; void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) override; void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence) override; void parseArgs(const Vector<String16>& args, std::string& result) override; void setMaxDisplayFrames(uint32_t size) override; + float computeFps(const std::unordered_set<int32_t>& layerIds) override; void reset() override; // Sets up the perfetto tracing backend and data source. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 141a112af1..937868a413 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1595,7 +1595,8 @@ void Layer::addSurfaceFramePresentedForBuffer( std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransaction( const FrameTimelineInfo& info, nsecs_t postTime) { auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName, + mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, + getSequence(), mName, mTransactionName); // For Transactions, the post time is considered to be both queue and acquire fence time. surfaceFrame->setActualQueueTime(postTime); @@ -1611,8 +1612,8 @@ std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransac std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer( const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName) { auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName, - debugName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, + getSequence(), mName, debugName); // For buffers, acquire fence time will set during latch. surfaceFrame->setActualQueueTime(queueTime); const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 14bb5b71ac..664c10b299 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -501,6 +501,7 @@ public: // one empty rect. virtual void useSurfaceDamage() {} virtual void useEmptyDamage() {} + Region getVisibleRegion(const DisplayDevice*) const; virtual void incrementPendingBufferCount() {} @@ -1009,6 +1010,7 @@ protected: // For unit tests friend class TestableSurfaceFlinger; + friend class FpsReporterTest; friend class RefreshRateSelectionTest; friend class SetFrameRateTest; friend class TransactionFrameTracerTest; @@ -1165,7 +1167,6 @@ private: virtual bool canDrawShadows() const { return true; } Hwc2::IComposerClient::Composition getCompositionType(const DisplayDevice&) const; - Region getVisibleRegion(const DisplayDevice*) const; /** * Returns an unsorted vector of all layers that are part of this tree. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4ee759f0b0..6a98e36d6a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -108,6 +108,7 @@ #include "DisplayRenderArea.h" #include "EffectLayer.h" #include "Effects/Daltonizer.h" +#include "FpsReporter.h" #include "FrameTimeline/FrameTimeline.h" #include "FrameTracer/FrameTracer.h" #include "Layer.h" @@ -254,6 +255,11 @@ private: std::function<void()> mCallback; }; +enum Permission { + ACCESS_SURFACE_FLINGER = 0x1, + ROTATE_SURFACE_FLINGER = 0x2, +}; + } // namespace anonymous struct SetInputWindowsListener : os::BnSetInputWindowsListener { @@ -966,9 +972,18 @@ status_t SurfaceFlinger::getDynamicDisplayInfo(const sp<IBinder>& displayToken, } info->activeColorMode = display->getCompositionDisplay()->getState().colorMode; - info->supportedColorModes = getDisplayColorModes(display->getPhysicalId()); + const auto displayId = display->getPhysicalId(); + info->supportedColorModes = getDisplayColorModes(displayId); info->hdrCapabilities = display->getHdrCapabilities(); + info->autoLowLatencyModeSupported = + getHwComposer().hasDisplayCapability(displayId, + hal::DisplayCapability::AUTO_LOW_LATENCY_MODE); + std::vector<hal::ContentType> types; + getHwComposer().getSupportedContentTypes(displayId, &types); + info->gameContentTypeSupported = std::any_of(types.begin(), types.end(), [](auto type) { + return type == hal::ContentType::GAME; + }); return NO_ERROR; } @@ -1243,24 +1258,6 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col return NO_ERROR; } -status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp<IBinder>& displayToken, - bool* outSupport) const { - if (!displayToken) { - return BAD_VALUE; - } - - Mutex::Autolock lock(mStateLock); - - const auto displayId = getPhysicalDisplayIdLocked(displayToken); - if (!displayId) { - return NAME_NOT_FOUND; - } - *outSupport = - getHwComposer().hasDisplayCapability(*displayId, - hal::DisplayCapability::AUTO_LOW_LATENCY_MODE); - return NO_ERROR; -} - void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) { static_cast<void>(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { @@ -1271,27 +1268,6 @@ void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool })); } -status_t SurfaceFlinger::getGameContentTypeSupport(const sp<IBinder>& displayToken, - bool* outSupport) const { - if (!displayToken) { - return BAD_VALUE; - } - - Mutex::Autolock lock(mStateLock); - - const auto displayId = getPhysicalDisplayIdLocked(displayToken); - if (!displayId) { - return NAME_NOT_FOUND; - } - - std::vector<hal::ContentType> types; - getHwComposer().getSupportedContentTypes(*displayId, &types); - - *outSupport = std::any_of(types.begin(), types.end(), - [](auto type) { return type == hal::ContentType::GAME; }); - return NO_ERROR; -} - void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) { static_cast<void>(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { @@ -1452,6 +1428,25 @@ status_t SurfaceFlinger::removeRegionSamplingListener(const sp<IRegionSamplingLi return NO_ERROR; } +status_t SurfaceFlinger::addFpsListener(const sp<IBinder>& layerHandle, + const sp<gui::IFpsListener>& listener) { + if (!listener) { + return BAD_VALUE; + } + + const wp<Layer> layer = fromHandle(layerHandle); + mFpsReporter->addListener(listener, layer); + return NO_ERROR; +} + +status_t SurfaceFlinger::removeFpsListener(const sp<gui::IFpsListener>& listener) { + if (!listener) { + return BAD_VALUE; + } + mFpsReporter->removeListener(listener); + return NO_ERROR; +} + status_t SurfaceFlinger::getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const { if (!displayToken || !outSupport) { @@ -2138,6 +2133,13 @@ void SurfaceFlinger::postComposition() { } }); + { + Mutex::Autolock lock(mStateLock); + if (mFpsReporter) { + mFpsReporter->dispatchLayerFps(); + } + } + mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0]); mTransactionCallbackInvoker.sendCallbacks(); @@ -2954,6 +2956,7 @@ void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) { mRegionSamplingThread = new RegionSamplingThread(*this, *mScheduler, RegionSamplingThread::EnvironmentTimingTunables()); + mFpsReporter = new FpsReporter(*mFrameTimeline); // Dispatch a mode change request for the primary display on scheduler // initialization, so that the EventThreads always contain a reference to a // prior configuration. @@ -3313,7 +3316,7 @@ void SurfaceFlinger::flushTransactionQueues() { transaction.displays, transaction.flags, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, transaction.buffer, - transaction.postTime, transaction.privileged, + transaction.postTime, transaction.permissions, transaction.hasListenerCallbacks, transaction.listenerCallbacks, transaction.originPid, transaction.originUid, transaction.id); } @@ -3386,16 +3389,23 @@ status_t SurfaceFlinger::setTransactionState( const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) { ATRACE_CALL(); - { - Mutex::Autolock _l(mQueueLock); + uint32_t permissions = + callingThreadHasUnscopedSurfaceFlingerAccess() ? Permission::ACCESS_SURFACE_FLINGER : 0; + // Avoid checking for rotation permissions if the caller already has ACCESS_SURFACE_FLINGER + // permissions. + if ((permissions & Permission::ACCESS_SURFACE_FLINGER) || + callingThreadHasRotateSurfaceFlingerAccess()) { + permissions |= Permission::ROTATE_SURFACE_FLINGER; + } - const int64_t postTime = systemTime(); - bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess(); + const int64_t postTime = systemTime(); - IPCThreadState* ipc = IPCThreadState::self(); - const int originPid = ipc->getCallingPid(); - const int originUid = ipc->getCallingUid(); + IPCThreadState* ipc = IPCThreadState::self(); + const int originPid = ipc->getCallingPid(); + const int originUid = ipc->getCallingUid(); + { + Mutex::Autolock _l(mQueueLock); // If its TransactionQueue already has a pending TransactionState or if it is pending auto itr = mPendingTransactionQueues.find(applyToken); // if this is an animation frame, wait until prior animation frame has @@ -3430,7 +3440,7 @@ status_t SurfaceFlinger::setTransactionState( mTransactionQueue.emplace(frameTimelineInfo, states, displays, flags, applyToken, inputWindowCommands, desiredPresentTime, isAutoTimestamp, - uncacheBuffer, postTime, privileged, hasListenerCallbacks, + uncacheBuffer, postTime, permissions, hasListenerCallbacks, listenerCallbacks, originPid, originUid, transactionId); if (pendingTransactions || @@ -3444,7 +3454,8 @@ status_t SurfaceFlinger::setTransactionState( ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]"); } - if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) { + if (!(permissions & Permission::ACCESS_SURFACE_FLINGER) && + (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) { ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags"); flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd); } @@ -3499,12 +3510,11 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, - const int64_t postTime, bool privileged, + const int64_t postTime, uint32_t permissions, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid, uint64_t transactionId) { uint32_t transactionFlags = 0; - for (const DisplayState& display : displays) { transactionFlags |= setDisplayStateLocked(display); } @@ -3522,7 +3532,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin for (const ComposerState& state : states) { clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp, - postTime, privileged, listenerCallbacksWithSurfaces); + postTime, permissions, listenerCallbacksWithSurfaces); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) { mScheduler->recordLayerHistory(layer.get(), @@ -3542,7 +3552,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin } transactionFlags |= clientStateFlags; - if (privileged) { + if (permissions & Permission::ACCESS_SURFACE_FLINGER) { transactionFlags |= addInputWindowCommands(inputWindowCommands); } else if (!inputWindowCommands.empty()) { ALOGE("Only privileged callers are allowed to send input commands."); @@ -3646,10 +3656,10 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis uint32_t SurfaceFlinger::setClientStateLocked( const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState, - int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, + int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions, std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) { const layer_state_t& s = composerState.state; - + const bool privileged = permissions & Permission::ACCESS_SURFACE_FLINGER; for (auto& listener : s.listeners) { // note that startRegistration will not re-register if the listener has // already be registered for a prior surface control @@ -3774,8 +3784,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( // ACCESS_SURFACE_FLINGER nor ROTATE_SURFACE_FLINGER // (a.k.a. everyone except WindowManager / tests / Launcher) from setting non rectangle // preserving transformations. - bool allowNonRectPreservingTransforms = - privileged || callingThreadHasRotateSurfaceFlingerAccess(); + const bool allowNonRectPreservingTransforms = + permissions & Permission::ROTATE_SURFACE_FLINGER; if (layer->setMatrix(s.matrix, allowNonRectPreservingTransforms)) flags |= eTraversalNeeded; } if (what & layer_state_t::eTransparentRegionChanged) { @@ -4942,6 +4952,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_DISPLAYED_CONTENT_SAMPLE: case NOTIFY_POWER_BOOST: case SET_GLOBAL_SHADOW_SETTINGS: + case ADD_FPS_LISTENER: + case REMOVE_FPS_LISTENER: case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: { // ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN is used by CTS tests, which acquire the // necessary permission dynamically. Don't use the permission cache for this check. diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 21cd2a5682..68f22e8081 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -89,6 +89,7 @@ namespace android { class Client; class EventThread; +class FpsReporter; class HWComposer; struct SetInputWindowsListener; class IGraphicBufferProducer; @@ -344,7 +345,8 @@ protected: virtual uint32_t setClientStateLocked( const FrameTimelineInfo& info, const ComposerState& composerState, - int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, + int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, + uint32_t permissions, std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) REQUIRES(mStateLock); virtual void commitTransactionLocked(); @@ -441,7 +443,7 @@ private: const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, - int64_t postTime, bool privileged, bool hasListenerCallbacks, + int64_t postTime, uint32_t permissions, bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks, int originPid, int originUid, uint64_t transactionId) : frameTimelineInfo(frameTimelineInfo), @@ -454,7 +456,7 @@ private: isAutoTimestamp(isAutoTimestamp), buffer(uncacheBuffer), postTime(postTime), - privileged(privileged), + permissions(permissions), hasListenerCallbacks(hasListenerCallbacks), listenerCallbacks(listenerCallbacks), originPid(originPid), @@ -471,7 +473,7 @@ private: const bool isAutoTimestamp; client_cache_t buffer; const int64_t postTime; - bool privileged; + uint32_t permissions; bool hasListenerCallbacks; std::vector<ListenerCallbacks> listenerCallbacks; int originPid; @@ -561,11 +563,7 @@ private: status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken, ui::DisplayPrimaries&) override; status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override; - status_t getAutoLowLatencyModeSupport(const sp<IBinder>& displayToken, - bool* outSupported) const override; void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) override; - status_t getGameContentTypeSupport(const sp<IBinder>& displayToken, - bool* outSupported) const override; void setGameContentType(const sp<IBinder>& displayToken, bool on) override; void setPowerMode(const sp<IBinder>& displayToken, int mode) override; status_t clearAnimationFrameStats() override; @@ -592,6 +590,9 @@ private: status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, const sp<IRegionSamplingListener>& listener) override; status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override; + status_t addFpsListener(const sp<IBinder>& layerHandle, + const sp<gui::IFpsListener>& listener) override; + status_t removeFpsListener(const sp<gui::IFpsListener>& listener) override; status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, ui::DisplayModeId displayModeId, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, @@ -740,7 +741,7 @@ private: const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, - bool privileged, bool hasListenerCallbacks, + uint32_t permissions, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid, uint64_t transactionId) REQUIRES(mStateLock); @@ -1268,6 +1269,7 @@ private: bool mLumaSampling = true; sp<RegionSamplingThread> mRegionSamplingThread; + sp<FpsReporter> mFpsReporter; ui::DisplayPrimaries mInternalDisplayPrimaries; const float mInternalDisplayDensity; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 2ac6b092b5..3c1b9d8c80 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -53,6 +53,7 @@ cc_test { "DisplayDevice_GetBestColorModeTest.cpp", "DisplayDevice_SetProjectionTest.cpp", "EventThreadTest.cpp", + "FpsReporterTest.cpp", "FpsTest.cpp", "FrameTimelineTest.cpp", "HWComposerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp new file mode 100644 index 0000000000..a9e5df3e9c --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp @@ -0,0 +1,184 @@ +/* + * Copyright 2021 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 "FpsReporterTest" + +#include <android/gui/BnFpsListener.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <gui/LayerMetadata.h> + +#include "BufferQueueLayer.h" +#include "BufferStateLayer.h" +#include "EffectLayer.h" +#include "FpsReporter.h" +#include "Layer.h" +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/MockEventThread.h" +#include "mock/MockFrameTimeline.h" +#include "mock/MockVsyncController.h" + +namespace android { + +using testing::_; +using testing::DoAll; +using testing::Mock; +using testing::Return; +using testing::SetArgPointee; +using testing::UnorderedElementsAre; + +using android::Hwc2::IComposer; +using android::Hwc2::IComposerClient; + +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; + +struct TestableFpsListener : public gui::BnFpsListener { + TestableFpsListener() {} + + float lastReportedFps = 0; + + binder::Status onFpsReported(float fps) override { + lastReportedFps = fps; + return binder::Status::ok(); + } +}; + +/** + * This class covers all the test that are related to refresh rate selection. + */ +class FpsReporterTest : public testing::Test { +public: + FpsReporterTest(); + ~FpsReporterTest() override; + +protected: + static constexpr int DEFAULT_DISPLAY_WIDTH = 1920; + static constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; + static constexpr uint32_t WIDTH = 100; + static constexpr uint32_t HEIGHT = 100; + static constexpr uint32_t LAYER_FLAGS = 0; + static constexpr int32_t PRIORITY_UNSET = -1; + + void setupScheduler(); + void setupComposer(uint32_t virtualDisplayCount); + sp<BufferStateLayer> createBufferStateLayer(); + + TestableSurfaceFlinger mFlinger; + Hwc2::mock::Composer* mComposer = nullptr; + mock::FrameTimeline mFrameTimeline = + mock::FrameTimeline(std::make_shared<impl::TimeStats>(), 0); + + sp<Client> mClient; + sp<Layer> mParent; + sp<Layer> mTarget; + sp<Layer> mChild; + sp<Layer> mGrandChild; + sp<Layer> mUnrelated; + + sp<TestableFpsListener> mFpsListener; + sp<FpsReporter> mFpsReporter = new FpsReporter(mFrameTimeline); +}; + +FpsReporterTest::FpsReporterTest() { + 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()); + + setupScheduler(); + setupComposer(0); + mFpsListener = new TestableFpsListener(); +} + +FpsReporterTest::~FpsReporterTest() { + 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()); +} + +sp<BufferStateLayer> FpsReporterTest::createBufferStateLayer() { + sp<Client> client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT, + LAYER_FLAGS, LayerMetadata()); + return new BufferStateLayer(args); +} + +void FpsReporterTest::setupScheduler() { + auto eventThread = std::make_unique<mock::EventThread>(); + auto sfEventThread = std::make_unique<mock::EventThread>(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + auto vsyncController = std::make_unique<mock::VsyncController>(); + auto vsyncTracker = std::make_unique<mock::VSyncTracker>(); + + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*vsyncTracker, currentPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), + std::move(eventThread), std::move(sfEventThread)); +} + +void FpsReporterTest::setupComposer(uint32_t virtualDisplayCount) { + mComposer = new Hwc2::mock::Composer(); + EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount)); + mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); + + Mock::VerifyAndClear(mComposer); +} + +namespace { + +TEST_F(FpsReporterTest, callsListeners) { + mParent = createBufferStateLayer(); + mTarget = createBufferStateLayer(); + mChild = createBufferStateLayer(); + mGrandChild = createBufferStateLayer(); + mUnrelated = createBufferStateLayer(); + mParent->addChild(mTarget); + mTarget->addChild(mChild); + mChild->addChild(mGrandChild); + mParent->commitChildList(); + + float expectedFps = 44.0; + + EXPECT_CALL(mFrameTimeline, + computeFps(UnorderedElementsAre(mTarget->getSequence(), mChild->getSequence(), + mGrandChild->getSequence()))) + .WillOnce(Return(expectedFps)); + + mFpsReporter->addListener(mFpsListener, mTarget); + mFpsReporter->dispatchLayerFps(); + EXPECT_EQ(expectedFps, mFpsListener->lastReportedFps); + mFpsReporter->removeListener(mFpsListener); + Mock::VerifyAndClearExpectations(&mFrameTimeline); + + EXPECT_CALL(mFrameTimeline, computeFps(_)).Times(0); + mFpsReporter->dispatchLayerFps(); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index b8c1607562..9a4e020468 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -170,6 +170,8 @@ static constexpr const uid_t sUidOne = 0; static constexpr pid_t sPidOne = 10; static constexpr pid_t sPidTwo = 20; static constexpr int32_t sInputEventId = 5; +static constexpr int32_t sLayerIdOne = 1; +static constexpr int32_t sLayerIdTwo = 2; TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) { int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0}); @@ -187,17 +189,20 @@ TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) { } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) { - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); - auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); + auto surfaceFrame2 = + mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne); EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo); } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None); } @@ -206,7 +211,7 @@ TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) { flushTokens(systemTime() + maxTokenRetentionTime); auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + sLayerIdOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired); } @@ -215,7 +220,7 @@ TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + sLayerIdOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid); EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true); @@ -226,7 +231,7 @@ TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) { constexpr int32_t inputEventId = 1; auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + sLayerIdOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId()); } @@ -236,7 +241,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + sLayerIdOne, sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11)); @@ -263,10 +268,12 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameTwo, sLayerNameTwo); + sUidOne, sLayerIdTwo, sLayerNameTwo, + sLayerNameTwo); mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -307,8 +314,8 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor}); auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, - sPidOne, sUidOne, sLayerNameOne, - sLayerNameOne); + sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11)); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -329,7 +336,8 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor}); auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11)); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -343,18 +351,18 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) { - auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue", - "acquireFenceAfterQueue"); + auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, sLayerIdOne, + "acquireFenceAfterQueue", + "acquireFenceAfterQueue"); surfaceFrame->setActualQueueTime(123); surfaceFrame->setAcquireFenceTime(456); EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) { - auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue", - "acquireFenceAfterQueue"); + auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, sLayerIdOne, + "acquireFenceAfterQueue", + "acquireFenceAfterQueue"); surfaceFrame->setActualQueueTime(456); surfaceFrame->setAcquireFenceTime(123); EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); @@ -367,8 +375,8 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Size shouldn't exceed maxDisplayFrames - 64 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, - sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11)); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -383,8 +391,8 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, - sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11)); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -399,8 +407,8 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, - sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11)); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -434,7 +442,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { std::chrono::nanoseconds(60ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(20ms).count()); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -460,7 +469,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { std::chrono::nanoseconds(60ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(20ms).count()); @@ -488,7 +498,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { std::chrono::nanoseconds(90ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(45ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate); @@ -519,7 +530,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) { std::chrono::nanoseconds(60ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(50ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate); @@ -550,7 +562,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) { std::chrono::nanoseconds(60ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(40ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate); @@ -580,7 +593,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { std::chrono::nanoseconds(90ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(40ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(82ms).count(), refreshRate); @@ -614,7 +628,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { std::chrono::nanoseconds(90ms).count()}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(45ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate); @@ -641,7 +656,7 @@ TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + sLayerIdOne, sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11)); @@ -667,7 +682,7 @@ TEST_F(FrameTimelineTest, tracing_sanityTest) { int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + sLayerIdOne, sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token2, 20, Fps::fromPeriodNsecs(11)); @@ -710,8 +725,9 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) tracingSession->StartBlocking(); int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11)); @@ -1015,10 +1031,12 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setActualQueueTime(10); surfaceFrame1->setDropTime(15); @@ -1174,7 +1192,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDoesNotTraceExpecte flushTokens(systemTime() + maxTokenRetentionTime); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0}, - sPidOne, sUidOne, sLayerNameOne, + sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setActualQueueTime(appEndTime); surfaceFrame1->setAcquireFenceTime(appEndTime); @@ -1246,7 +1264,8 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30}); auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -1401,7 +1420,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(16); mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1420,7 +1440,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame2->setAcquireFenceTime(36); mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11)); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1479,7 +1500,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(16); mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1498,7 +1520,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame2->setAcquireFenceTime(36); mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11)); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1556,7 +1579,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(40); mFrameTimeline->setSfWakeUp(sfToken1, 42, Fps::fromPeriodNsecs(11)); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1599,7 +1623,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(26); mFrameTimeline->setSfWakeUp(sfToken1, 32, Fps::fromPeriodNsecs(11)); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1618,7 +1643,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame2->setAcquireFenceTime(40); mFrameTimeline->setSfWakeUp(sfToken2, 43, Fps::fromPeriodNsecs(11)); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1671,7 +1697,8 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 116, 120}); auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame1->setAcquireFenceTime(50); mFrameTimeline->setSfWakeUp(sfToken1, 52, Fps::fromPeriodNsecs(30)); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1690,7 +1717,8 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, - sUidOne, sLayerNameOne, sLayerNameOne); + sUidOne, sLayerIdOne, sLayerNameOne, + sLayerNameOne); surfaceFrame2->setAcquireFenceTime(84); mFrameTimeline->setSfWakeUp(sfToken2, 112, Fps::fromPeriodNsecs(30)); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54); @@ -1735,4 +1763,151 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::AppDeadlineMissed | JankType::BufferStuffing); } + +TEST_F(FrameTimelineTest, computeFps_noLayerIds_returnsZero) { + EXPECT_EQ(mFrameTimeline->computeFps({}), 0.0f); +} + +TEST_F(FrameTimelineTest, computeFps_singleDisplayFrame_returnsZero) { + const auto oneHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count(); + + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame1); + presentFence1->signalForTest(oneHundredMs); + mFrameTimeline->setSfPresent(oneHundredMs, presentFence1); + + EXPECT_EQ(mFrameTimeline->computeFps({sLayerIdOne}), 0.0f); +} + +TEST_F(FrameTimelineTest, computeFps_twoDisplayFrames_oneLayer) { + const auto oneHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count(); + const auto twoHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(200ms).count(); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame1); + presentFence1->signalForTest(oneHundredMs); + mFrameTimeline->setSfPresent(oneHundredMs, presentFence1); + + auto surfaceFrame2 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame2); + presentFence2->signalForTest(twoHundredMs); + mFrameTimeline->setSfPresent(twoHundredMs, presentFence2); + + EXPECT_EQ(mFrameTimeline->computeFps({sLayerIdOne}), 10.0); +} + +TEST_F(FrameTimelineTest, computeFps_twoDisplayFrames_twoLayers) { + const auto oneHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count(); + const auto twoHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(200ms).count(); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame1); + presentFence1->signalForTest(oneHundredMs); + mFrameTimeline->setSfPresent(oneHundredMs, presentFence1); + + auto surfaceFrame2 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdTwo, sLayerNameTwo, sLayerNameTwo); + auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame2); + presentFence2->signalForTest(twoHundredMs); + mFrameTimeline->setSfPresent(twoHundredMs, presentFence2); + + EXPECT_EQ(mFrameTimeline->computeFps({sLayerIdOne, sLayerIdTwo}), 10.0f); +} + +TEST_F(FrameTimelineTest, computeFps_filtersOutLayers) { + const auto oneHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count(); + const auto twoHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(200ms).count(); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame1); + presentFence1->signalForTest(oneHundredMs); + mFrameTimeline->setSfPresent(oneHundredMs, presentFence1); + + auto surfaceFrame2 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdTwo, sLayerNameTwo, sLayerNameTwo); + auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame2); + presentFence2->signalForTest(twoHundredMs); + mFrameTimeline->setSfPresent(twoHundredMs, presentFence2); + + EXPECT_EQ(mFrameTimeline->computeFps({sLayerIdOne}), 0.0f); +} + +TEST_F(FrameTimelineTest, computeFps_averagesOverMultipleFrames) { + const auto oneHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count(); + const auto twoHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(200ms).count(); + const auto threeHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(300ms).count(); + const auto fiveHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(500ms).count(); + const auto sixHundredMs = std::chrono::duration_cast<std::chrono::nanoseconds>(600ms).count(); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame1); + presentFence1->signalForTest(oneHundredMs); + mFrameTimeline->setSfPresent(oneHundredMs, presentFence1); + + auto surfaceFrame2 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame2); + presentFence2->signalForTest(twoHundredMs); + mFrameTimeline->setSfPresent(twoHundredMs, presentFence2); + + auto surfaceFrame3 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdTwo, sLayerNameTwo, sLayerNameTwo); + auto presentFence3 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame3); + presentFence3->signalForTest(threeHundredMs); + mFrameTimeline->setSfPresent(threeHundredMs, presentFence3); + + auto surfaceFrame4 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence4 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + surfaceFrame4->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame4); + presentFence4->signalForTest(fiveHundredMs); + mFrameTimeline->setSfPresent(fiveHundredMs, presentFence4); + + auto surfaceFrame5 = + mFrameTimeline->createSurfaceFrameForToken(FrameTimelineInfo(), sPidOne, sUidOne, + sLayerIdOne, sLayerNameOne, sLayerNameOne); + auto presentFence5 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + // Dropped frames will be excluded from fps computation + surfaceFrame5->setPresentState(SurfaceFrame::PresentState::Dropped); + mFrameTimeline->addSurfaceFrame(surfaceFrame5); + presentFence5->signalForTest(sixHundredMs); + mFrameTimeline->setSfPresent(sixHundredMs, presentFence5); + + EXPECT_EQ(mFrameTimeline->computeFps({sLayerIdOne}), 5.0f); +} + } // namespace android::frametimeline diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h index 44b9b73fd4..b9d17946b9 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h @@ -33,6 +33,7 @@ public: MOCK_METHOD1(addSurfaceFrame, void(std::shared_ptr<frametimeline::SurfaceFrame>)); MOCK_METHOD3(setSfWakeUp, void(int64_t, nsecs_t, Fps)); MOCK_METHOD2(setSfPresent, void(nsecs_t, const std::shared_ptr<FenceTime>&)); + MOCK_METHOD1(computeFps, float(const std::unordered_set<int32_t>&)); }; } // namespace android::mock diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp index 4f893539c3..2002bdf628 100644 --- a/services/vibratorservice/Android.bp +++ b/services/vibratorservice/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libvibratorservice", diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp index 7b4cc199ba..a468146bc0 100644 --- a/services/vibratorservice/benchmarks/Android.bp +++ b/services/vibratorservice/benchmarks/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_benchmark { name: "libvibratorservice_benchmarks", srcs: [ diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp index ad85990c05..32947246d8 100644 --- a/services/vibratorservice/test/Android.bp +++ b/services/vibratorservice/test/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libvibratorservice_test", test_suites: ["device-tests"], diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index 2d4690a2af..d1cd397da4 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -33,6 +33,7 @@ #include <unordered_set> #include <utility> +#include <android-base/properties.h> #include <android-base/strings.h> #include <cutils/properties.h> #include <log/log.h> @@ -134,7 +135,7 @@ class OverrideLayerNames { // If no layers specified via Settings, check legacy properties if (implicit_layers_.count <= 0) { ParseDebugVulkanLayers(); - property_list(ParseDebugVulkanLayer, this); + ParseDebugVulkanLayer(); // sort by priorities auto& arr = implicit_layers_; @@ -181,30 +182,39 @@ class OverrideLayerNames { AddImplicitLayer(prio, p, strlen(p)); } - static void ParseDebugVulkanLayer(const char* key, - const char* val, - void* user_data) { + void ParseDebugVulkanLayer() { + // Checks for consecutive debug.vulkan.layer.<priority> system + // properties after always checking an initial fixed range. static const char prefix[] = "debug.vulkan.layer."; - const size_t prefix_len = sizeof(prefix) - 1; - - if (strncmp(key, prefix, prefix_len) || val[0] == '\0') - return; - key += prefix_len; - - // debug.vulkan.layer.<priority> - int priority = -1; - if (key[0] >= '0' && key[0] <= '9') - priority = atoi(key); + static constexpr int kFixedRangeBeginInclusive = 0; + static constexpr int kFixedRangeEndInclusive = 9; + + bool logged = false; + + int priority = kFixedRangeBeginInclusive; + while (true) { + const std::string prop_key = + std::string(prefix) + std::to_string(priority); + const std::string prop_val = + android::base::GetProperty(prop_key, ""); + + if (!prop_val.empty()) { + if (!logged) { + ALOGI( + "Detected Vulkan layers configured with " + "debug.vulkan.layer.<priority>. Checking for " + "debug.vulkan.layer.<priority> in the range [%d, %d] " + "followed by a consecutive scan.", + kFixedRangeBeginInclusive, kFixedRangeEndInclusive); + logged = true; + } + AddImplicitLayer(priority, prop_val.c_str(), prop_val.length()); + } else if (priority >= kFixedRangeEndInclusive) { + return; + } - if (priority < 0) { - ALOGW("Ignored implicit layer %s with invalid priority %s", val, - key); - return; + ++priority; } - - OverrideLayerNames& override_layers = - *reinterpret_cast<OverrideLayerNames*>(user_data); - override_layers.AddImplicitLayer(priority, val, strlen(val)); } void AddImplicitLayer(int priority, const char* name, size_t len) { |