Merge changes I6e236efc,I4e333f34,I061a6986 into sc-dev
* changes:
Cleanup Skia RE display and layer colorTransforms
Avoid unnecessary computation for shadows and clipping for rounded layers
Use stack based cleanup for canvas save/restore calls.
diff --git a/aidl/gui/android/hardware/display/IDeviceProductInfoConstants.aidl b/aidl/gui/android/hardware/display/IDeviceProductInfoConstants.aidl
deleted file mode 100644
index 7cc272a..0000000
--- a/aidl/gui/android/hardware/display/IDeviceProductInfoConstants.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.display;
-
-/** @hide */
-interface IDeviceProductInfoConstants {
- /** The device connection to the display sink is unknown. */
- const int CONNECTION_TO_SINK_UNKNOWN = 0;
-
- /** 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;
-}
\ No newline at end of file
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index c7c3a34..006e532 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -37,12 +37,18 @@
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 @@
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 @@
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 @@
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 6c86c21..9186514 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -18,8 +18,3 @@
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/idlcli/CommandVibrator.cpp b/cmds/idlcli/CommandVibrator.cpp
index a7a70c3..81bdbe2 100644
--- a/cmds/idlcli/CommandVibrator.cpp
+++ b/cmds/idlcli/CommandVibrator.cpp
@@ -22,7 +22,7 @@
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 dd84304..24a40d9 100644
--- a/cmds/idlcli/IdlCli.h
+++ b/cmds/idlcli/IdlCli.h
@@ -25,14 +25,47 @@
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 9ed9d82..308f294 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 b874455..262f2e5 100644
--- a/cmds/idlcli/utils.h
+++ b/cmds/idlcli/utils.h
@@ -249,7 +249,7 @@
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 6c30a9e..dfbb886 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 @@
}
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 @@
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 @@
} // namespace idlcli
} // namespace android
-
-#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 8039bb0..cc5420e 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -127,6 +127,10 @@
* to listen directly to DisplayManager.DisplayListener#onDisplayChanged events
* instead.
*
+ * As of API level 31, this api is guaranteed to have a consistent view with DisplayManager;
+ * Display#getRefreshRate is guaranteed to not return a stale refresh rate when invoked from this
+ * callback.
+ *
* Available since API level 30.
*/
void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
diff --git a/include/android/input.h b/include/android/input.h
index b70d424..7973487 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -859,7 +859,7 @@
/** HDMI */
AINPUT_SOURCE_HDMI = 0x02000000 | AINPUT_SOURCE_CLASS_BUTTON,
/** sensor */
- AINPUT_SOURCE_SENSOR = 0x04000000 | AINPUT_SOURCE_UNKNOWN,
+ AINPUT_SOURCE_SENSOR = 0x04000000 | AINPUT_SOURCE_CLASS_NONE,
/** rotary encoder */
AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 2bd7bd2..2deb99d 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -100,6 +100,13 @@
SPECIAL_TRIGGER = 3,
};
+enum class InputDeviceLightType : int32_t {
+ SINGLE = 0,
+ PLAYER_ID = 1,
+ RGB = 2,
+ MULTI_COLOR = 3,
+};
+
struct InputDeviceSensorInfo {
explicit InputDeviceSensorInfo(std::string name, std::string vendor, int32_t version,
InputDeviceSensorType type, InputDeviceSensorAccuracy accuracy,
@@ -156,6 +163,20 @@
int32_t id;
};
+struct InputDeviceLightInfo {
+ explicit InputDeviceLightInfo(std::string name, int32_t id, InputDeviceLightType type,
+ int32_t ordinal)
+ : name(name), id(id), type(type), ordinal(ordinal) {}
+ // Name string of the light.
+ std::string name;
+ // Light id
+ int32_t id;
+ // Type of the light.
+ InputDeviceLightType type;
+ // Ordinal of the light
+ int32_t ordinal;
+};
+
/*
* Describes the characteristics and capabilities of an input device.
*/
@@ -198,6 +219,7 @@
float min, float max, float flat, float fuzz, float resolution);
void addMotionRange(const MotionRange& range);
void addSensorInfo(const InputDeviceSensorInfo& info);
+ void addLightInfo(const InputDeviceLightInfo& info);
inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
inline int32_t getKeyboardType() const { return mKeyboardType; }
@@ -230,6 +252,10 @@
const std::vector<InputDeviceSensorType> getSensorTypes();
+ const std::vector<int32_t> getLightIds();
+
+ const InputDeviceLightInfo* getLightInfo(int32_t id);
+
private:
int32_t mId;
int32_t mGeneration;
@@ -248,6 +274,8 @@
std::vector<MotionRange> mMotionRanges;
std::unordered_map<InputDeviceSensorType, InputDeviceSensorInfo> mSensors;
+ /* Map from light ID to light info */
+ std::unordered_map<int32_t, InputDeviceLightInfo> mLights;
};
/* Types of input device configuration files. */
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 2e90142..1fbaa13 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 4580751..5df0012 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 @@
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 cef0bf3..8d08275 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -118,6 +118,7 @@
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 cb0987e..1ccd0d2 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::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 @@
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 @@
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 de1a48d..6a88401 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 @@
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/gui/Android.bp b/libs/gui/Android.bp
index debd664..dc91fc6 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -143,7 +143,12 @@
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 2e4f858..eba7b3c 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -411,24 +411,6 @@
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 +436,6 @@
}
}
- 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());
@@ -1423,23 +1388,6 @@
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 +1405,6 @@
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 +1422,6 @@
setGameContentType(display, setGameContentTypeOn);
return result;
}
-
case CLEAR_ANIMATION_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
status_t result = clearAnimationFrameStats();
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index cdde9a2..e707684 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -61,6 +61,7 @@
RETURN_ON_ERROR(parcel->writeBool(mRefreshPending));
RETURN_ON_ERROR(parcel->writeBool(mIsOpaque));
RETURN_ON_ERROR(parcel->writeBool(mContentDirty));
+ RETURN_ON_ERROR(parcel->write(mStretchEffect));
return NO_ERROR;
}
@@ -105,6 +106,7 @@
RETURN_ON_ERROR(parcel->readBool(&mRefreshPending));
RETURN_ON_ERROR(parcel->readBool(&mIsOpaque));
RETURN_ON_ERROR(parcel->readBool(&mContentDirty));
+ RETURN_ON_ERROR(parcel->read(mStretchEffect));
return NO_ERROR;
}
@@ -115,6 +117,12 @@
info.mTransparentRegion.dump(result, "TransparentRegion");
info.mVisibleRegion.dump(result, "VisibleRegion");
info.mSurfaceDamageRegion.dump(result, "SurfaceDamageRegion");
+ if (info.mStretchEffect.hasEffect()) {
+ const auto& se = info.mStretchEffect;
+ StringAppendF(&result, " StretchEffect area=[%f, %f, %f, %f] vec=(%f, %f) maxAmount=%f\n",
+ se.area.left, se.area.top, se.area.right, se.area.bottom, se.vectorX,
+ se.vectorY, se.maxAmount);
+ }
StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ",
info.mLayerStack, info.mZ, static_cast<double>(info.mX),
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index f053372..288bf92 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -548,6 +548,10 @@
what |= eAutoRefreshChanged;
autoRefresh = other.autoRefresh;
}
+ if (other.what & eStretchChanged) {
+ what |= eStretchChanged;
+ stretchEffect = other.stretchEffect;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1a643c2..0317b2b 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1904,22 +1904,10 @@
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);
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index d0ab480..6289e5a 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -219,32 +219,17 @@
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;
@@ -563,9 +548,9 @@
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,
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index 66a7b4d..8b7d32c 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -20,6 +20,7 @@
#include <ui/PixelFormat.h>
#include <ui/Region.h>
+#include <ui/StretchEffect.h>
#include <string>
#include <math/vec4.h>
@@ -66,6 +67,7 @@
bool mRefreshPending = false;
bool mIsOpaque = false;
bool mContentDirty = false;
+ StretchEffect mStretchEffect = {};
};
std::string to_string(const LayerDebugInfo& info);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 6f0f18c..64c8af5 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -143,17 +143,11 @@
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);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3397198..69bb866 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -757,15 +757,7 @@
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 {
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 698cf6e..ffcc1cd 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -170,7 +170,8 @@
mHasButtonUnderPad(other.mHasButtonUnderPad),
mHasSensor(other.mHasSensor),
mMotionRanges(other.mMotionRanges),
- mSensors(other.mSensors) {}
+ mSensors(other.mSensors),
+ mLights(other.mLights) {}
InputDeviceInfo::~InputDeviceInfo() {
}
@@ -193,6 +194,7 @@
mHasSensor = false;
mMotionRanges.clear();
mSensors.clear();
+ mLights.clear();
}
const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
@@ -229,6 +231,13 @@
mSensors.insert_or_assign(info.type, info);
}
+void InputDeviceInfo::addLightInfo(const InputDeviceLightInfo& info) {
+ if (mLights.find(info.id) != mLights.end()) {
+ ALOGW("Light id %d already exists, will be replaced by new light added.", info.id);
+ }
+ mLights.insert_or_assign(info.id, info);
+}
+
const std::vector<InputDeviceSensorType> InputDeviceInfo::getSensorTypes() {
std::vector<InputDeviceSensorType> types;
for (const auto& [type, info] : mSensors) {
@@ -245,4 +254,20 @@
return &it->second;
}
+const std::vector<int32_t> InputDeviceInfo::getLightIds() {
+ std::vector<int32_t> ids;
+ for (const auto& [id, info] : mLights) {
+ ids.push_back(id);
+ }
+ return ids;
+}
+
+const InputDeviceLightInfo* InputDeviceInfo::getLightInfo(int32_t id) {
+ auto it = mLights.find(id);
+ if (it == mLights.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
} // namespace android
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 3cf9f3f..907eb67 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -39,6 +39,7 @@
"com.android.media.swcodec",
"com.android.neuralnetworks",
],
+
min_sdk_version: "29",
export_include_dirs: ["include"],
@@ -49,4 +50,23 @@
}
}
+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 6fb149a..72d33bc 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 0000000..e91b52b
--- /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 20f852f..0dac662 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 @@
}
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 @@
// -------------------------------------------------------------------------------------
} // 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 617a0ab..5ec9bf7 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 @@
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 4a7c4dd..14fb72a 100644
--- a/libs/math/tests/Android.bp
+++ b/libs/math/tests/Android.bp
@@ -50,3 +50,10 @@
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 604072e..a514d98 100644
--- a/libs/math/tests/half_test.cpp
+++ b/libs/math/tests/half_test.cpp
@@ -94,4 +94,13 @@
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 0000000..96c6e81
--- /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/ui/Android.bp b/libs/ui/Android.bp
index ac0ae72..de2b9a4 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -238,9 +238,11 @@
},
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 11acdae..d5c4ef0 100644
--- a/libs/ui/DynamicDisplayInfo.cpp
+++ b/libs/ui/DynamicDisplayInfo.cpp
@@ -39,7 +39,9 @@
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 @@
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 @@
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 5110a6c..a0b5fe7 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 6c349b7..a4c2f71 100644
--- a/libs/ui/include/ui/DynamicDisplayInfo.h
+++ b/libs/ui/include/ui/DynamicDisplayInfo.h
@@ -41,6 +41,14 @@
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 bec2552..4c9c7b7 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 {
@@ -48,6 +49,8 @@
float top = 0.0f;
float right = 0.0f;
float bottom = 0.0f;
+
+ constexpr bool isEmpty() const { return !(left < right && top < bottom); }
};
inline bool operator==(const FloatRect& a, const FloatRect& b) {
@@ -60,3 +63,13 @@
}
} // 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 58323e5..9e24a07 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 @@
}; // 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 6bb7b8d..927c334 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 @@
// ---------------------------------------------------------------------------
}; // 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/include/ui/StretchEffect.h b/libs/ui/include/ui/StretchEffect.h
index 1d2460c..0803df3 100644
--- a/libs/ui/include/ui/StretchEffect.h
+++ b/libs/ui/include/ui/StretchEffect.h
@@ -19,6 +19,7 @@
#include <utils/Flattenable.h>
#include "FloatRect.h"
+#include <math.h>
#include <type_traits>
namespace android {
@@ -45,7 +46,7 @@
void sanitize() {
// If the area is empty, or the max amount is zero, then reset back to defaults
- if (area.bottom >= area.top || area.left >= area.right || isZero(maxAmount)) {
+ if (area.isEmpty() || isZero(maxAmount)) {
*this = StretchEffect{};
}
}
diff --git a/libs/ui/tests/Rect_test.cpp b/libs/ui/tests/Rect_test.cpp
index 5499a5b..9cc36bb 100644
--- a/libs/ui/tests/Rect_test.cpp
+++ b/libs/ui/tests/Rect_test.cpp
@@ -259,4 +259,33 @@
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 c6b826d..74924bd 100644
--- a/libs/ui/tests/Region_test.cpp
+++ b/libs/ui/tests/Region_test.cpp
@@ -167,5 +167,17 @@
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 4b1f350..33b3e1e 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -50,9 +50,10 @@
// --- 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 @@
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 @@
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 @@
// --- 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 @@
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 @@
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 @@
}
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 d6b7259..182736f 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -249,8 +249,9 @@
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/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 094bc0c..4b7d26d 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -73,12 +73,14 @@
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 @@
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/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 69aea84..3bf212a 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -113,6 +113,10 @@
/* Get battery status of a particular input device. */
virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0;
+ virtual std::vector<int32_t> getLightIds(int32_t deviceId) = 0;
+
+ virtual const InputDeviceLightInfo* getLightInfo(int32_t deviceId, int32_t lightId) = 0;
+
/* Return true if the device can send input events to the specified display. */
virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
@@ -126,6 +130,15 @@
/* Flush sensor data in input reader mapper. */
virtual void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0;
+
+ /* Set color for the light */
+ virtual bool setLightColor(int32_t deviceId, int32_t lightId, int32_t color) = 0;
+ /* Set player ID for the light */
+ virtual bool setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) = 0;
+ /* Get light color */
+ virtual std::optional<int32_t> getLightColor(int32_t deviceId, int32_t lightId) = 0;
+ /* Get light player ID */
+ virtual std::optional<int32_t> getLightPlayerId(int32_t deviceId, int32_t lightId) = 0;
};
// --- InputReaderConfiguration ---
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 518e295..8a2828c 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -45,6 +45,7 @@
"mapper/InputMapper.cpp",
"mapper/JoystickInputMapper.cpp",
"mapper/KeyboardInputMapper.cpp",
+ "mapper/LightInputMapper.cpp",
"mapper/MultiTouchInputMapper.cpp",
"mapper/RotaryEncoderInputMapper.cpp",
"mapper/SensorInputMapper.cpp",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 8f8c051..a0d3b6a 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -48,6 +48,7 @@
#include <utils/Timers.h>
#include <filesystem>
+#include <regex>
#include "EventHub.h"
@@ -84,6 +85,30 @@
{"Full", 100},
{"Unknown", 50}};
+// Mapping for input led class node names lookup.
+// https://www.kernel.org/doc/html/latest/leds/leds-class.html
+static const std::unordered_map<std::string, InputLightClass> LIGHT_CLASSES =
+ {{"red", InputLightClass::RED},
+ {"green", InputLightClass::GREEN},
+ {"blue", InputLightClass::BLUE},
+ {"global", InputLightClass::GLOBAL},
+ {"brightness", InputLightClass::BRIGHTNESS},
+ {"multi_index", InputLightClass::MULTI_INDEX},
+ {"multi_intensity", InputLightClass::MULTI_INTENSITY},
+ {"max_brightness", InputLightClass::MAX_BRIGHTNESS}};
+
+// Mapping for input multicolor led class node names.
+// https://www.kernel.org/doc/html/latest/leds/leds-class-multicolor.html
+static const std::unordered_map<InputLightClass, std::string> LIGHT_NODES =
+ {{InputLightClass::BRIGHTNESS, "brightness"},
+ {InputLightClass::MULTI_INDEX, "multi_index"},
+ {InputLightClass::MULTI_INTENSITY, "multi_intensity"}};
+
+// Mapping for light color name and the light color
+const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
+ {"green", LightColor::GREEN},
+ {"blue", LightColor::BLUE}};
+
static inline const char* toString(bool value) {
return value ? "true" : "false";
}
@@ -151,14 +176,14 @@
* Returns the sysfs root path of the input device
*
*/
-static std::filesystem::path getSysfsRootPath(const char* devicePath) {
+static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) {
std::error_code errorCode;
// Stat the device path to get the major and minor number of the character file
struct stat statbuf;
if (stat(devicePath, &statbuf) == -1) {
ALOGE("Could not stat device %s due to error: %s.", devicePath, std::strerror(errno));
- return std::filesystem::path();
+ return std::nullopt;
}
unsigned int major_num = major(statbuf.st_rdev);
@@ -173,7 +198,7 @@
if (errorCode) {
ALOGW("Could not run filesystem::canonical() due to error %d : %s.", errorCode.value(),
errorCode.message().c_str());
- return std::filesystem::path();
+ return std::nullopt;
}
// Continue to go up a directory until we reach a directory named "input"
@@ -192,26 +217,68 @@
}
// Not found
- return std::filesystem::path();
+ return std::nullopt;
}
return sysfsPath;
}
/**
- * Returns the power supply node in sys fs
- *
+ * Returns the list of files under a specified path.
*/
-static std::filesystem::path findPowerSupplyNode(const std::filesystem::path& sysfsRootPath) {
- for (auto path = sysfsRootPath; path != "/"; path = path.parent_path()) {
- std::error_code errorCode;
- auto iter = std::filesystem::directory_iterator(path / "power_supply", errorCode);
- if (!errorCode && iter != std::filesystem::directory_iterator()) {
- return iter->path();
+static std::vector<std::filesystem::path> allFilesInPath(const std::filesystem::path& path) {
+ std::vector<std::filesystem::path> nodes;
+ std::error_code errorCode;
+ auto iter = std::filesystem::directory_iterator(path, errorCode);
+ while (!errorCode && iter != std::filesystem::directory_iterator()) {
+ nodes.push_back(iter->path());
+ iter++;
+ }
+ return nodes;
+}
+
+/**
+ * Returns the list of files under a specified directory in a sysfs path.
+ * Example:
+ * findSysfsNodes(sysfsRootPath, SysfsClass::LEDS) will return all led nodes under "leds" directory
+ * in the sysfs path.
+ */
+static std::vector<std::filesystem::path> findSysfsNodes(const std::filesystem::path& sysfsRoot,
+ SysfsClass clazz) {
+ std::string nodeStr = NamedEnum::string(clazz);
+ std::for_each(nodeStr.begin(), nodeStr.end(),
+ [](char& c) { c = std::tolower(static_cast<unsigned char>(c)); });
+ std::vector<std::filesystem::path> nodes;
+ for (auto path = sysfsRoot; path != "/" && nodes.empty(); path = path.parent_path()) {
+ nodes = allFilesInPath(path / nodeStr);
+ }
+ return nodes;
+}
+
+static std::optional<std::array<LightColor, COLOR_NUM>> getColorIndexArray(
+ std::filesystem::path path) {
+ std::string indexStr;
+ if (!base::ReadFileToString(path, &indexStr)) {
+ return std::nullopt;
+ }
+
+ // Parse the multi color LED index file, refer to kernel docs
+ // leds/leds-class-multicolor.html
+ std::regex indexPattern("(red|green|blue)\\s(red|green|blue)\\s(red|green|blue)[\\n]");
+ std::smatch results;
+ std::array<LightColor, COLOR_NUM> colors;
+ if (!std::regex_match(indexStr, results, indexPattern)) {
+ return std::nullopt;
+ }
+
+ for (size_t i = 1; i < results.size(); i++) {
+ const auto it = LIGHT_COLORS.find(results[i].str());
+ if (it != LIGHT_COLORS.end()) {
+ // intensities.emplace(it->second, 0);
+ colors[i - 1] = it->second;
}
}
- // Not found
- return std::filesystem::path();
+ return colors;
}
// --- Global Functions ---
@@ -280,6 +347,7 @@
virtualKeyMap(nullptr),
ffEffectPlaying(false),
ffEffectId(-1),
+ nextLightId(0),
controllerNumber(0),
enabled(true),
isVirtual(fd < 0) {}
@@ -469,6 +537,70 @@
return NAME_NOT_FOUND;
}
+// Check the sysfs path for any input device batteries, returns true if battery found.
+bool EventHub::Device::configureBatteryLocked() {
+ if (!sysfsRootPath.has_value()) {
+ return false;
+ }
+ // Check if device has any batteries.
+ std::vector<std::filesystem::path> batteryPaths =
+ findSysfsNodes(sysfsRootPath.value(), SysfsClass::POWER_SUPPLY);
+ // We only support single battery for an input device, if multiple batteries exist only the
+ // first one is supported.
+ if (batteryPaths.empty()) {
+ // Set path to be empty
+ sysfsBatteryPath = std::nullopt;
+ return false;
+ }
+ // If a battery exists
+ sysfsBatteryPath = batteryPaths[0];
+ return true;
+}
+
+// Check the sysfs path for any input device lights, returns true if lights found.
+bool EventHub::Device::configureLightsLocked() {
+ if (!sysfsRootPath.has_value()) {
+ return false;
+ }
+ // Check if device has any lights.
+ const auto& paths = findSysfsNodes(sysfsRootPath.value(), SysfsClass::LEDS);
+ for (const auto& nodePath : paths) {
+ RawLightInfo info;
+ info.id = ++nextLightId;
+ info.path = nodePath;
+ info.name = nodePath.filename();
+ info.maxBrightness = std::nullopt;
+ size_t nameStart = info.name.rfind(":");
+ if (nameStart != std::string::npos) {
+ // Trim the name to color name
+ info.name = info.name.substr(nameStart + 1);
+ // Set InputLightClass flag for colors
+ const auto it = LIGHT_CLASSES.find(info.name);
+ if (it != LIGHT_CLASSES.end()) {
+ info.flags |= it->second;
+ }
+ }
+ // Scan the path for all the files
+ // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
+ const auto& files = allFilesInPath(nodePath);
+ for (const auto& file : files) {
+ const auto it = LIGHT_CLASSES.find(file.filename().string());
+ if (it != LIGHT_CLASSES.end()) {
+ info.flags |= it->second;
+ // If the node has maximum brightness, read it
+ if (it->second == InputLightClass::MAX_BRIGHTNESS) {
+ std::string str;
+ if (base::ReadFileToString(file, &str)) {
+ info.maxBrightness = std::stoi(str);
+ }
+ }
+ }
+ }
+ lightInfos.insert_or_assign(info.id, info);
+ }
+ return !lightInfos.empty();
+}
+
/**
* Get the capabilities for the current process.
* Crashes the system if unable to create / check / destroy the capabilities object.
@@ -829,6 +961,161 @@
return Errorf("Device not found or device has no key layout.");
}
+const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::vector<int32_t> lightIds;
+
+ if (device != nullptr) {
+ for (const auto [id, info] : device->lightInfos) {
+ lightIds.push_back(id);
+ }
+ }
+ return lightIds;
+}
+
+std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+
+ if (device != nullptr) {
+ auto it = device->lightInfos.find(lightId);
+ if (it != device->lightInfos.end()) {
+ return it->second;
+ }
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) {
+ std::scoped_lock _l(mLock);
+
+ Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr) {
+ return std::nullopt;
+ }
+
+ auto it = device->lightInfos.find(lightId);
+ if (it == device->lightInfos.end()) {
+ return std::nullopt;
+ }
+ std::string buffer;
+ if (!base::ReadFileToString(it->second.path / LIGHT_NODES.at(InputLightClass::BRIGHTNESS),
+ &buffer)) {
+ return std::nullopt;
+ }
+ return std::stoi(buffer);
+}
+
+std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensities(
+ int32_t deviceId, int32_t lightId) {
+ std::scoped_lock _l(mLock);
+
+ Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr) {
+ return std::nullopt;
+ }
+
+ auto lightIt = device->lightInfos.find(lightId);
+ if (lightIt == device->lightInfos.end()) {
+ return std::nullopt;
+ }
+
+ auto ret =
+ getColorIndexArray(lightIt->second.path / LIGHT_NODES.at(InputLightClass::MULTI_INDEX));
+
+ if (!ret.has_value()) {
+ return std::nullopt;
+ }
+ std::array<LightColor, COLOR_NUM> colors = ret.value();
+
+ std::string intensityStr;
+ if (!base::ReadFileToString(lightIt->second.path /
+ LIGHT_NODES.at(InputLightClass::MULTI_INTENSITY),
+ &intensityStr)) {
+ return std::nullopt;
+ }
+
+ // Intensity node outputs 3 color values
+ std::regex intensityPattern("([0-9]+)\\s([0-9]+)\\s([0-9]+)[\\n]");
+ std::smatch results;
+
+ if (!std::regex_match(intensityStr, results, intensityPattern)) {
+ return std::nullopt;
+ }
+ std::unordered_map<LightColor, int32_t> intensities;
+ for (size_t i = 1; i < results.size(); i++) {
+ int value = std::stoi(results[i].str());
+ intensities.emplace(colors[i - 1], value);
+ }
+ return intensities;
+}
+
+void EventHub::setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) {
+ std::scoped_lock _l(mLock);
+
+ Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr) {
+ ALOGE("Device Id %d does not exist", deviceId);
+ return;
+ }
+ auto lightIt = device->lightInfos.find(lightId);
+ if (lightIt == device->lightInfos.end()) {
+ ALOGE("Light Id %d does not exist.", lightId);
+ return;
+ }
+
+ if (!base::WriteStringToFile(std::to_string(brightness),
+ lightIt->second.path /
+ LIGHT_NODES.at(InputLightClass::BRIGHTNESS))) {
+ ALOGE("Can not write to file, error: %s", strerror(errno));
+ }
+}
+
+void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId,
+ std::unordered_map<LightColor, int32_t> intensities) {
+ std::scoped_lock _l(mLock);
+
+ Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr) {
+ ALOGE("Device Id %d does not exist", deviceId);
+ return;
+ }
+ auto lightIt = device->lightInfos.find(lightId);
+ if (lightIt == device->lightInfos.end()) {
+ ALOGE("Light Id %d does not exist.", lightId);
+ return;
+ }
+
+ auto ret =
+ getColorIndexArray(lightIt->second.path / LIGHT_NODES.at(InputLightClass::MULTI_INDEX));
+
+ if (!ret.has_value()) {
+ return;
+ }
+ std::array<LightColor, COLOR_NUM> colors = ret.value();
+
+ std::string rgbStr;
+ for (size_t i = 0; i < COLOR_NUM; i++) {
+ auto it = intensities.find(colors[i]);
+ if (it != intensities.end()) {
+ rgbStr += std::to_string(it->second);
+ // Insert space between colors
+ if (i < COLOR_NUM - 1) {
+ rgbStr += " ";
+ }
+ }
+ }
+ // Append new line
+ rgbStr += "\n";
+
+ if (!base::WriteStringToFile(rgbStr,
+ lightIt->second.path /
+ LIGHT_NODES.at(InputLightClass::MULTI_INTENSITY))) {
+ ALOGE("Can not write to file, error: %s", strerror(errno));
+ }
+}
+
void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
std::scoped_lock _l(mLock);
@@ -1068,18 +1355,18 @@
Device* device = getDeviceLocked(deviceId);
std::string buffer;
- if (!device || (device->sysfsBatteryPath.empty())) {
+ if (device == nullptr || !device->sysfsBatteryPath.has_value()) {
return std::nullopt;
}
// Some devices report battery capacity as an integer through the "capacity" file
- if (base::ReadFileToString(device->sysfsBatteryPath / "capacity", &buffer)) {
+ if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity", &buffer)) {
return std::stoi(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 / "capacity_level", &buffer)) {
+ if (base::ReadFileToString(device->sysfsBatteryPath.value() / "capacity_level", &buffer)) {
const auto it = BATTERY_LEVEL.find(buffer);
if (it != BATTERY_LEVEL.end()) {
return it->second;
@@ -1093,11 +1380,11 @@
Device* device = getDeviceLocked(deviceId);
std::string buffer;
- if (!device || (device->sysfsBatteryPath.empty())) {
+ if (device == nullptr || !device->sysfsBatteryPath.has_value()) {
return std::nullopt;
}
- if (!base::ReadFileToString(device->sysfsBatteryPath / "status", &buffer)) {
+ if (!base::ReadFileToString(device->sysfsBatteryPath.value() / "status", &buffer)) {
ALOGE("Failed to read sysfs battery info: %s", strerror(errno));
return std::nullopt;
}
@@ -1280,6 +1567,7 @@
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;
@@ -1572,6 +1860,12 @@
// Load the configuration file for the device.
device->loadConfigurationLocked();
+ // Grab the device's sysfs path
+ device->sysfsRootPath = getSysfsRootPath(devicePath.c_str());
+ // find related components
+ bool hasBattery = device->configureBatteryLocked();
+ bool hasLights = device->configureLightsLocked();
+
// Figure out the kinds of events the device reports.
device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
@@ -1721,16 +2015,14 @@
return -1;
}
- // Grab the device's sysfs path
- device->sysfsRootPath = getSysfsRootPath(devicePath.c_str());
+ // Classify InputDeviceClass::BATTERY.
+ if (hasBattery) {
+ device->classes |= InputDeviceClass::BATTERY;
+ }
- if (!device->sysfsRootPath.empty()) {
- device->sysfsBatteryPath = findPowerSupplyNode(device->sysfsRootPath);
-
- // Check if a battery exists
- if (!device->sysfsBatteryPath.empty()) {
- device->classes |= InputDeviceClass::BATTERY;
- }
+ // Classify InputDeviceClass::LIGHT.
+ if (hasLights) {
+ device->classes |= InputDeviceClass::LIGHT;
}
// Determine whether the device has a mic.
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 574f651..dd1abeb 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -27,6 +27,7 @@
#include "InputReaderContext.h"
#include "JoystickInputMapper.h"
#include "KeyboardInputMapper.h"
+#include "LightInputMapper.h"
#include "MultiTouchInputMapper.h"
#include "RotaryEncoderInputMapper.h"
#include "SensorInputMapper.h"
@@ -161,9 +162,22 @@
mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
}
- // Battery-like devices.
+ // Battery-like devices. Only one battery mapper for each EventHub device.
if (classes.test(InputDeviceClass::BATTERY)) {
- mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr));
+ InputDeviceInfo deviceInfo;
+ getDeviceInfo(&deviceInfo);
+ if (!deviceInfo.hasBattery()) {
+ mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr));
+ }
+ }
+
+ // Light-containing devices. Only one light mapper for each EventHub device.
+ if (classes.test(InputDeviceClass::LIGHT)) {
+ InputDeviceInfo deviceInfo;
+ getDeviceInfo(&deviceInfo);
+ if (deviceInfo.getLightIds().empty()) {
+ mappers.push_back(std::make_unique<LightInputMapper>(*contextPtr));
+ }
}
// Keyboard-like devices.
@@ -492,8 +506,8 @@
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() {
@@ -505,6 +519,32 @@
return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); });
}
+bool InputDevice::setLightColor(int32_t lightId, int32_t color) {
+ bool success = true;
+ for_each_mapper([&success, lightId, color](InputMapper& mapper) {
+ success &= mapper.setLightColor(lightId, color);
+ });
+ return success;
+}
+
+bool InputDevice::setLightPlayerId(int32_t lightId, int32_t playerId) {
+ bool success = true;
+ for_each_mapper([&success, lightId, playerId](InputMapper& mapper) {
+ success &= mapper.setLightPlayerId(lightId, playerId);
+ });
+ return success;
+}
+
+std::optional<int32_t> InputDevice::getLightColor(int32_t lightId) {
+ return first_in_mappers<int32_t>(
+ [lightId](InputMapper& mapper) { return mapper.getLightColor(lightId); });
+}
+
+std::optional<int32_t> InputDevice::getLightPlayerId(int32_t lightId) {
+ return first_in_mappers<int32_t>(
+ [lightId](InputMapper& mapper) { return mapper.getLightPlayerId(lightId); });
+}
+
int32_t InputDevice::getMetaState() {
int32_t result = 0;
for_each_mapper([&result](InputMapper& mapper) { result |= mapper.getMetaState(); });
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 14fb77b..2d0fdf7 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -696,6 +696,70 @@
return std::nullopt;
}
+std::vector<int32_t> InputReader::getLightIds(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ InputDeviceInfo info;
+ device->getDeviceInfo(&info);
+ return info.getLightIds();
+ }
+ return {};
+}
+
+const InputDeviceLightInfo* InputReader::getLightInfo(int32_t deviceId, int32_t lightId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ InputDeviceInfo info;
+ device->getDeviceInfo(&info);
+ return info.getLightInfo(lightId);
+ }
+ return nullptr;
+}
+
+bool InputReader::setLightColor(int32_t deviceId, int32_t lightId, int32_t color) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->setLightColor(lightId, color);
+ }
+ return false;
+}
+
+bool InputReader::setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->setLightPlayerId(lightId, playerId);
+ }
+ return false;
+}
+
+std::optional<int32_t> InputReader::getLightColor(int32_t deviceId, int32_t lightId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getLightColor(lightId);
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> InputReader::getLightPlayerId(int32_t deviceId, int32_t lightId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getLightPlayerId(lightId);
+ }
+ return std::nullopt;
+}
+
bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
std::scoped_lock _l(mLock);
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 30967df..4059729 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -47,11 +47,17 @@
namespace android {
+/* Number of colors : {red, green, blue} */
+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;
@@ -127,6 +133,9 @@
/* The input device has a battery */
BATTERY = 0x00004000,
+ /* The input device has sysfs controllable lights */
+ LIGHT = 0x00008000,
+
/* The input device is virtual (not a real device, not part of UI configuration). */
VIRTUAL = 0x40000000,
@@ -134,6 +143,46 @@
EXTERNAL = 0x80000000,
};
+enum class SysfsClass : uint32_t {
+ POWER_SUPPLY = 0,
+ LEDS = 1,
+};
+
+enum class LightColor : uint32_t {
+ RED = 0,
+ GREEN = 1,
+ BLUE = 2,
+};
+
+enum class InputLightClass : uint32_t {
+ /* The input light has brightness node. */
+ BRIGHTNESS = 0x00000001,
+ /* The input light has red name. */
+ RED = 0x00000002,
+ /* The input light has green name. */
+ GREEN = 0x00000004,
+ /* The input light has blue name. */
+ BLUE = 0x00000008,
+ /* The input light has global name. */
+ GLOBAL = 0x00000010,
+ /* The input light has multi index node. */
+ MULTI_INDEX = 0x00000020,
+ /* The input light has multi intensity node. */
+ MULTI_INTENSITY = 0x00000040,
+ /* The input light has max brightness node. */
+ MAX_BRIGHTNESS = 0x00000080,
+};
+
+/* Describes a raw light. */
+struct RawLightInfo {
+ int32_t id;
+ std::string name;
+ std::optional<int32_t> maxBrightness;
+ Flags<InputLightClass> flags;
+ std::array<int32_t, COLOR_NUM> rgbIndex;
+ std::filesystem::path path;
+};
+
/*
* Gets the class that owns an axis, in cases where multiple classes might claim
* the same axis for different purposes.
@@ -214,7 +263,16 @@
virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
int32_t absCode) = 0;
-
+ // Raw lights are sysfs led light nodes we found from the EventHub device sysfs node,
+ // containing the raw info of the sysfs node structure.
+ virtual const std::vector<int32_t> getRawLightIds(int32_t deviceId) = 0;
+ virtual std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) = 0;
+ virtual std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) = 0;
+ virtual void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) = 0;
+ virtual std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
+ int32_t deviceId, int32_t lightId) = 0;
+ virtual void setLightIntensities(int32_t deviceId, int32_t lightId,
+ std::unordered_map<LightColor, int32_t> intensities) = 0;
/*
* Query current input state.
*/
@@ -377,6 +435,17 @@
base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
int32_t deviceId, int32_t absCode) override final;
+ const std::vector<int32_t> getRawLightIds(int32_t deviceId) override final;
+
+ std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override final;
+
+ std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override final;
+ void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override final;
+ std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
+ int32_t deviceId, int32_t lightId) override final;
+ void setLightIntensities(int32_t deviceId, int32_t lightId,
+ std::unordered_map<LightColor, int32_t> intensities) override final;
+
void setExcludedDevices(const std::vector<std::string>& devices) override final;
int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final;
@@ -458,9 +527,12 @@
bool ffEffectPlaying;
int16_t ffEffectId; // initially -1
- // The paths are invalid when .empty() returns true
- std::filesystem::path sysfsRootPath;
- std::filesystem::path sysfsBatteryPath;
+ // The paths are invalid when they're std::nullopt
+ std::optional<std::filesystem::path> sysfsRootPath;
+ std::optional<std::filesystem::path> sysfsBatteryPath;
+ // maps from light id to light info
+ std::unordered_map<int32_t, RawLightInfo> lightInfos;
+ int32_t nextLightId;
int32_t controllerNumber;
@@ -491,6 +563,8 @@
void setLedForControllerLocked();
status_t mapLed(int32_t led, int32_t* outScanCode) const;
void setLedStateLocked(int32_t led, bool on);
+ bool configureBatteryLocked();
+ bool configureLightsLocked();
};
status_t openDeviceLocked(const std::string& devicePath);
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index e4186c8..863cd41 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -86,7 +86,7 @@
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);
@@ -95,6 +95,11 @@
std::optional<int32_t> getBatteryCapacity();
std::optional<int32_t> getBatteryStatus();
+ bool setLightColor(int32_t lightId, int32_t color);
+ bool setLightPlayerId(int32_t lightId, int32_t playerId);
+ std::optional<int32_t> getLightColor(int32_t lightId);
+ std::optional<int32_t> getLightPlayerId(int32_t lightId);
+
int32_t getMetaState();
void updateMetaState(int32_t keyCode);
@@ -254,6 +259,30 @@
return mEventHub->mapSensor(mId, absCode);
}
+ inline const std::vector<int32_t> getRawLightIds() { return mEventHub->getRawLightIds(mId); }
+
+ inline std::optional<RawLightInfo> getRawLightInfo(int32_t lightId) {
+ return mEventHub->getRawLightInfo(mId, lightId);
+ }
+
+ inline std::optional<int32_t> getLightBrightness(int32_t lightId) {
+ return mEventHub->getLightBrightness(mId, lightId);
+ }
+
+ inline void setLightBrightness(int32_t lightId, int32_t brightness) {
+ return mEventHub->setLightBrightness(mId, lightId, brightness);
+ }
+
+ inline std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
+ int32_t lightId) {
+ return mEventHub->getLightIntensities(mId, lightId);
+ }
+
+ inline void setLightIntensities(int32_t lightId,
+ std::unordered_map<LightColor, int32_t> intensities) {
+ return mEventHub->setLightIntensities(mId, lightId, intensities);
+ }
+
inline std::vector<TouchVideoFrame> getVideoFrames() { return mEventHub->getVideoFrames(mId); }
inline int32_t getScanCodeState(int32_t scanCode) const {
return mEventHub->getScanCodeState(mId, scanCode);
@@ -322,7 +351,7 @@
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/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 81e3e9a..1405671 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -99,6 +99,18 @@
std::optional<int32_t> getBatteryStatus(int32_t deviceId) override;
+ std::vector<int32_t> getLightIds(int32_t deviceId) override;
+
+ const InputDeviceLightInfo* getLightInfo(int32_t deviceId, int32_t lightId) override;
+
+ bool setLightColor(int32_t deviceId, int32_t lightId, int32_t color) override;
+
+ bool setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) override;
+
+ std::optional<int32_t> getLightColor(int32_t deviceId, int32_t lightId) override;
+
+ std::optional<int32_t> getLightPlayerId(int32_t deviceId, int32_t lightId) override;
+
protected:
// These members are protected so they can be instrumented by test cases.
virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId,
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.cpp b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
index afdc5ab..e4fb3a6 100644
--- a/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
@@ -24,7 +24,7 @@
: InputMapper(deviceContext) {}
uint32_t BatteryInputMapper::getSources() {
- return 0;
+ return AINPUT_SOURCE_UNKNOWN;
}
void BatteryInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 254b64b..bb12be7 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -265,11 +265,11 @@
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 @@
}
// 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 @@
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 @@
}
}
- 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 @@
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 @@
// 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 @@
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 @@
}
// 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 05bbb26..9a8ca01 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -114,7 +114,7 @@
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 1ce54ae..df1acd4 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -68,7 +68,7 @@
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 1cc5979..15cff1c 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -67,7 +67,7 @@
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);
@@ -77,6 +77,11 @@
virtual std::optional<int32_t> getBatteryCapacity() { return std::nullopt; }
virtual std::optional<int32_t> getBatteryStatus() { return std::nullopt; }
+ virtual bool setLightColor(int32_t lightId, int32_t color) { return true; }
+ virtual bool setLightPlayerId(int32_t lightId, int32_t playerId) { return true; }
+ virtual std::optional<int32_t> getLightColor(int32_t lightId) { return std::nullopt; }
+ virtual std::optional<int32_t> getLightPlayerId(int32_t lightId) { return std::nullopt; }
+
virtual int32_t getMetaState();
virtual void updateMetaState(int32_t keyCode);
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index 37aa140..0dc312e 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -299,14 +299,14 @@
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 @@
// 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 0cf60a2..bba95ad 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -92,7 +92,7 @@
// 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 8b9f235..2c5a576 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -216,7 +216,8 @@
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 @@
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 @@
return;
}
if (policyFlags & POLICY_FLAG_GESTURE) {
- getDeviceContext().cancelTouch(when);
+ getDeviceContext().cancelTouch(when, readTime);
}
KeyDown keyDown;
@@ -350,8 +352,9 @@
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 4c0b42a..ca41712 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -86,7 +86,7 @@
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.cpp b/services/inputflinger/reader/mapper/LightInputMapper.cpp
new file mode 100644
index 0000000..be1f722
--- /dev/null
+++ b/services/inputflinger/reader/mapper/LightInputMapper.cpp
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <locale>
+#include <regex>
+
+#include "../Macros.h"
+
+#include "LightInputMapper.h"
+#include "input/NamedEnum.h"
+
+// Log detailed debug messages about input device lights.
+static constexpr bool DEBUG_LIGHT_DETAILS = false;
+
+namespace android {
+
+static inline int32_t getAlpha(int32_t color) {
+ return (color >> 24) & 0xff;
+}
+
+static inline int32_t getRed(int32_t color) {
+ return (color >> 16) & 0xff;
+}
+
+static inline int32_t getGreen(int32_t color) {
+ return (color >> 8) & 0xff;
+}
+
+static inline int32_t getBlue(int32_t color) {
+ return color & 0xff;
+}
+
+static inline int32_t toArgb(int32_t brightness, int32_t red, int32_t green, int32_t blue) {
+ return (brightness & 0xff) << 24 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff);
+}
+
+/**
+ * Light input mapper owned by InputReader device, implements the native API for querying input
+ * lights, getting and setting the lights brightness and color, by interacting with EventHub
+ * devices.
+ * TODO b/180342233: Reconsider the inputflinger design to accommodate the device class
+ * like lights and battery.
+ */
+LightInputMapper::LightInputMapper(InputDeviceContext& deviceContext)
+ : InputMapper(deviceContext) {}
+
+LightInputMapper::~LightInputMapper() {}
+
+std::optional<std::int32_t> LightInputMapper::Light::getRawLightBrightness(int32_t rawLightId) {
+ std::optional<RawLightInfo> rawInfo = context.getRawLightInfo(rawLightId);
+ std::optional<int32_t> ret = context.getLightBrightness(rawLightId);
+ if (!rawInfo.has_value() || !ret.has_value()) {
+ return std::nullopt;
+ }
+ int brightness = ret.value();
+
+ // If the light node doesn't have max brightness, use the default max brightness.
+ int rawMaxBrightness = rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS);
+ float ratio = MAX_BRIGHTNESS / rawMaxBrightness;
+ // Scale the returned brightness in [0, rawMaxBrightness] to [0, 255]
+ if (rawMaxBrightness != MAX_BRIGHTNESS) {
+ brightness = brightness * ratio;
+ }
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("getRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f", rawLightId,
+ brightness, ratio);
+ }
+ return brightness;
+}
+
+void LightInputMapper::Light::setRawLightBrightness(int32_t rawLightId, int32_t brightness) {
+ std::optional<RawLightInfo> rawInfo = context.getRawLightInfo(rawLightId);
+ if (!rawInfo.has_value()) {
+ return;
+ }
+ // If the light node doesn't have max brightness, use the default max brightness.
+ int rawMaxBrightness = rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS);
+ float ratio = MAX_BRIGHTNESS / rawMaxBrightness;
+ // Scale the requested brightness in [0, 255] to [0, rawMaxBrightness]
+ if (rawMaxBrightness != MAX_BRIGHTNESS) {
+ brightness = ceil(brightness / ratio);
+ }
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("setRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f", rawLightId,
+ brightness, ratio);
+ }
+ context.setLightBrightness(rawLightId, brightness);
+}
+
+bool LightInputMapper::SingleLight::setLightColor(int32_t color) {
+ int32_t brightness = getAlpha(color);
+ setRawLightBrightness(rawId, brightness);
+
+ return true;
+}
+
+bool LightInputMapper::RgbLight::setLightColor(int32_t color) {
+ // Compose color value as per:
+ // https://developer.android.com/reference/android/graphics/Color?hl=en
+ // int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);
+ // The alpha component is used to scale the R,G,B leds brightness, with the ratio to
+ // MAX_BRIGHTNESS.
+ brightness = getAlpha(color);
+ int32_t red = 0;
+ int32_t green = 0;
+ int32_t blue = 0;
+ if (brightness > 0) {
+ float ratio = MAX_BRIGHTNESS / brightness;
+ red = ceil(getRed(color) / ratio);
+ green = ceil(getGreen(color) / ratio);
+ blue = ceil(getBlue(color) / ratio);
+ }
+ setRawLightBrightness(rawRgbIds.at(LightColor::RED), red);
+ setRawLightBrightness(rawRgbIds.at(LightColor::GREEN), green);
+ setRawLightBrightness(rawRgbIds.at(LightColor::BLUE), blue);
+ if (rawGlobalId.has_value()) {
+ setRawLightBrightness(rawGlobalId.value(), brightness);
+ }
+
+ return true;
+}
+
+bool LightInputMapper::MultiColorLight::setLightColor(int32_t color) {
+ std::unordered_map<LightColor, int32_t> intensities;
+ intensities.emplace(LightColor::RED, getRed(color));
+ intensities.emplace(LightColor::GREEN, getGreen(color));
+ intensities.emplace(LightColor::BLUE, getBlue(color));
+
+ context.setLightIntensities(rawId, intensities);
+ setRawLightBrightness(rawId, getAlpha(color));
+ return true;
+}
+
+std::optional<int32_t> LightInputMapper::SingleLight::getLightColor() {
+ std::optional<int32_t> brightness = getRawLightBrightness(rawId);
+ if (!brightness.has_value()) {
+ return std::nullopt;
+ }
+
+ return toArgb(brightness.value(), 0 /* red */, 0 /* green */, 0 /* blue */);
+}
+
+std::optional<int32_t> LightInputMapper::RgbLight::getLightColor() {
+ // If the Alpha component is zero, then return color 0.
+ if (brightness == 0) {
+ return 0;
+ }
+ // Compose color value as per:
+ // https://developer.android.com/reference/android/graphics/Color?hl=en
+ // int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);
+ std::optional<int32_t> redOr = getRawLightBrightness(rawRgbIds.at(LightColor::RED));
+ std::optional<int32_t> greenOr = getRawLightBrightness(rawRgbIds.at(LightColor::GREEN));
+ std::optional<int32_t> blueOr = getRawLightBrightness(rawRgbIds.at(LightColor::BLUE));
+ // If we can't get brightness for any of the RGB light
+ if (!redOr.has_value() || !greenOr.has_value() || !blueOr.has_value()) {
+ return std::nullopt;
+ }
+
+ // Compose the ARGB format color. As the R,G,B color led brightness is scaled by Alpha
+ // value, scale it back to return the nominal color value.
+ float ratio = MAX_BRIGHTNESS / brightness;
+ int32_t red = round(redOr.value() * ratio);
+ int32_t green = round(greenOr.value() * ratio);
+ int32_t blue = round(blueOr.value() * ratio);
+
+ if (red > MAX_BRIGHTNESS || green > MAX_BRIGHTNESS || blue > MAX_BRIGHTNESS) {
+ // Previously stored brightness isn't valid for current LED values, so just reset to max
+ // brightness since an app couldn't have provided these values in the first place.
+ red = redOr.value();
+ green = greenOr.value();
+ blue = blueOr.value();
+ brightness = MAX_BRIGHTNESS;
+ }
+
+ return toArgb(brightness, red, green, blue);
+}
+
+std::optional<int32_t> LightInputMapper::MultiColorLight::getLightColor() {
+ auto ret = context.getLightIntensities(rawId);
+ if (!ret.has_value()) {
+ return std::nullopt;
+ }
+ std::unordered_map<LightColor, int32_t> intensities = ret.value();
+ // Get red, green, blue colors
+ int32_t color = toArgb(0 /* brightness */, intensities.at(LightColor::RED) /* red */,
+ intensities.at(LightColor::GREEN) /* green */,
+ intensities.at(LightColor::BLUE) /* blue */);
+ // Get brightness
+ std::optional<int32_t> brightness = getRawLightBrightness(rawId);
+ if (brightness.has_value()) {
+ return toArgb(brightness.value() /* A */, 0, 0, 0) | color;
+ }
+ return std::nullopt;
+}
+
+bool LightInputMapper::PlayerIdLight::setLightPlayerId(int32_t playerId) {
+ if (rawLightIds.find(playerId) == rawLightIds.end()) {
+ return false;
+ }
+ for (const auto& [id, rawId] : rawLightIds) {
+ if (playerId == id) {
+ setRawLightBrightness(rawId, MAX_BRIGHTNESS);
+ } else {
+ setRawLightBrightness(rawId, 0);
+ }
+ }
+ return true;
+}
+
+std::optional<int32_t> LightInputMapper::PlayerIdLight::getLightPlayerId() {
+ for (const auto& [id, rawId] : rawLightIds) {
+ std::optional<int32_t> brightness = getRawLightBrightness(rawId);
+ if (brightness.has_value() && brightness.value() > 0) {
+ return id;
+ }
+ }
+ return std::nullopt;
+}
+
+void LightInputMapper::SingleLight::dump(std::string& dump) {
+ dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
+}
+
+void LightInputMapper::PlayerIdLight::dump(std::string& dump) {
+ dump += StringPrintf(INDENT4 "PlayerId: %d\n", getLightPlayerId().value_or(-1));
+ dump += StringPrintf(INDENT4 "Raw Player ID LEDs:");
+ for (const auto& [id, rawId] : rawLightIds) {
+ dump += StringPrintf("id %d -> %d ", id, rawId);
+ }
+ dump += "\n";
+}
+
+void LightInputMapper::RgbLight::dump(std::string& dump) {
+ dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
+ dump += StringPrintf(INDENT4 "Raw RGB LEDs: [%d, %d, %d] ", rawRgbIds.at(LightColor::RED),
+ rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
+ if (rawGlobalId.has_value()) {
+ dump += StringPrintf(INDENT4 "Raw Global LED: [%d] ", rawGlobalId.value());
+ }
+ dump += "\n";
+}
+
+void LightInputMapper::MultiColorLight::dump(std::string& dump) {
+ dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0));
+}
+
+uint32_t LightInputMapper::getSources() {
+ return AINPUT_SOURCE_UNKNOWN;
+}
+
+void LightInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ for (const auto& [lightId, light] : mLights) {
+ // Input device light doesn't support ordinal, always pass 1.
+ InputDeviceLightInfo lightInfo(light->name, light->id, light->type, 1 /* ordinal */);
+ info->addLightInfo(lightInfo);
+ }
+}
+
+void LightInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Light Input Mapper:\n";
+ dump += INDENT3 "Lights:\n";
+ for (const auto& [lightId, light] : mLights) {
+ dump += StringPrintf(INDENT4 "Id: %d", lightId);
+ dump += StringPrintf(INDENT4 "Name: %s", light->name.c_str());
+ dump += StringPrintf(INDENT4 "Type: %s", NamedEnum::string(light->type).c_str());
+ light->dump(dump);
+ }
+ // Dump raw lights
+ dump += INDENT3 "RawLights:\n";
+ dump += INDENT4 "Id:\t Name:\t Flags:\t Max brightness:\t Brightness\n";
+ const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
+ // Map from raw light id to raw light info
+ std::unordered_map<int32_t, RawLightInfo> rawInfos;
+ for (const auto& rawId : rawLightIds) {
+ std::optional<RawLightInfo> rawInfo = getDeviceContext().getRawLightInfo(rawId);
+ if (!rawInfo.has_value()) {
+ continue;
+ }
+ dump += StringPrintf(INDENT4 "%d", rawId);
+ dump += StringPrintf(INDENT4 "%s", rawInfo->name.c_str());
+ dump += StringPrintf(INDENT4 "%s", rawInfo->flags.string().c_str());
+ dump += StringPrintf(INDENT4 "%d", rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS));
+ dump += StringPrintf(INDENT4 "%d\n",
+ getDeviceContext().getLightBrightness(rawId).value_or(-1));
+ }
+}
+
+void LightInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config,
+ uint32_t changes) {
+ InputMapper::configure(when, config, changes);
+
+ if (!changes) { // first time only
+ bool hasRedLed = false;
+ bool hasGreenLed = false;
+ bool hasBlueLed = false;
+ std::optional<int32_t> rawGlobalId = std::nullopt;
+ // Player ID light common name string
+ std::string playerIdName;
+ // Raw RGB color to raw light ID
+ std::unordered_map<LightColor, int32_t /* rawLightId */> rawRgbIds;
+ // Map from player Id to raw light Id
+ std::unordered_map<int32_t, int32_t> playerIdLightIds;
+ mLights.clear();
+
+ // Check raw lights
+ const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
+ // Map from raw light id to raw light info
+ std::unordered_map<int32_t, RawLightInfo> rawInfos;
+ for (const auto& rawId : rawLightIds) {
+ std::optional<RawLightInfo> rawInfo = getDeviceContext().getRawLightInfo(rawId);
+ if (!rawInfo.has_value()) {
+ continue;
+ }
+ rawInfos.insert_or_assign(rawId, rawInfo.value());
+ // Check if this is a group LEDs for player ID
+ std::regex lightPattern("([a-z]+)([0-9]+)");
+ std::smatch results;
+ if (std::regex_match(rawInfo->name, results, lightPattern)) {
+ std::string commonName = results[1].str();
+ int32_t playerId = std::stoi(results[2]);
+ if (playerIdLightIds.empty()) {
+ playerIdName = commonName;
+ playerIdLightIds.insert_or_assign(playerId, rawId);
+ } else {
+ // Make sure the player ID leds have common string name
+ if (playerIdName.compare(commonName) == 0 &&
+ playerIdLightIds.find(playerId) == playerIdLightIds.end()) {
+ playerIdLightIds.insert_or_assign(playerId, rawId);
+ }
+ }
+ }
+ // Check if this is an LED of RGB light
+ if (rawInfo->flags.test(InputLightClass::RED)) {
+ hasRedLed = true;
+ rawRgbIds.emplace(LightColor::RED, rawId);
+ }
+ if (rawInfo->flags.test(InputLightClass::GREEN)) {
+ hasGreenLed = true;
+ rawRgbIds.emplace(LightColor::GREEN, rawId);
+ }
+ if (rawInfo->flags.test(InputLightClass::BLUE)) {
+ hasBlueLed = true;
+ rawRgbIds.emplace(LightColor::BLUE, rawId);
+ }
+ if (rawInfo->flags.test(InputLightClass::GLOBAL)) {
+ rawGlobalId = rawId;
+ }
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("Light rawId %d name %s max %d flags %s \n", rawInfo->id,
+ rawInfo->name.c_str(), rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS),
+ rawInfo->flags.string().c_str());
+ }
+ }
+
+ // Construct a player ID light
+ if (playerIdLightIds.size() > 1) {
+ std::unique_ptr<Light> light =
+ std::make_unique<PlayerIdLight>(getDeviceContext(), playerIdName, ++mNextId,
+ playerIdLightIds);
+ mLights.insert_or_assign(light->id, std::move(light));
+ // Remove these raw lights from raw light info as they've been used to compose a
+ // Player ID light, so we do not expose these raw lights as single lights.
+ for (const auto& [playerId, rawId] : playerIdLightIds) {
+ rawInfos.erase(rawId);
+ }
+ }
+ // Construct a RGB light for composed RGB light
+ if (hasRedLed && hasGreenLed && hasBlueLed) {
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("Rgb light ids [%d, %d, %d] \n", rawRgbIds.at(LightColor::RED),
+ rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
+ }
+ std::unique_ptr<Light> light = std::make_unique<RgbLight>(getDeviceContext(), ++mNextId,
+ rawRgbIds, rawGlobalId);
+ mLights.insert_or_assign(light->id, std::move(light));
+ // Remove from raw light info as they've been composed a RBG light.
+ rawInfos.erase(rawRgbIds.at(LightColor::RED));
+ rawInfos.erase(rawRgbIds.at(LightColor::GREEN));
+ rawInfos.erase(rawRgbIds.at(LightColor::BLUE));
+ if (rawGlobalId.has_value()) {
+ rawInfos.erase(rawGlobalId.value());
+ }
+ }
+
+ // Check the rest of raw light infos
+ for (const auto& [rawId, rawInfo] : rawInfos) {
+ // If the node is multi-color led, construct a MULTI_COLOR light
+ if (rawInfo.flags.test(InputLightClass::MULTI_INDEX) &&
+ rawInfo.flags.test(InputLightClass::MULTI_INTENSITY)) {
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("Multicolor light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
+ }
+ std::unique_ptr<Light> light =
+ std::make_unique<MultiColorLight>(getDeviceContext(), rawInfo.name,
+ ++mNextId, rawInfo.id);
+ mLights.insert_or_assign(light->id, std::move(light));
+ continue;
+ }
+ // Construct a single LED light
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("Single light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
+ }
+ std::unique_ptr<Light> light =
+ std::make_unique<SingleLight>(getDeviceContext(), rawInfo.name, ++mNextId,
+ rawInfo.id);
+
+ mLights.insert_or_assign(light->id, std::move(light));
+ }
+ }
+}
+
+void LightInputMapper::reset(nsecs_t when) {
+ InputMapper::reset(when);
+}
+
+void LightInputMapper::process(const RawEvent* rawEvent) {}
+
+bool LightInputMapper::setLightColor(int32_t lightId, int32_t color) {
+ auto it = mLights.find(lightId);
+ if (it == mLights.end()) {
+ return false;
+ }
+ auto& light = it->second;
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("setLightColor lightId %d type %s color 0x%x", lightId,
+ NamedEnum::string(light->type).c_str(), color);
+ }
+ return light->setLightColor(color);
+}
+
+std::optional<int32_t> LightInputMapper::getLightColor(int32_t lightId) {
+ auto it = mLights.find(lightId);
+ if (it == mLights.end()) {
+ return std::nullopt;
+ }
+ auto& light = it->second;
+ std::optional<int32_t> color = light->getLightColor();
+ if (DEBUG_LIGHT_DETAILS) {
+ ALOGD("getLightColor lightId %d type %s color 0x%x", lightId,
+ NamedEnum::string(light->type).c_str(), color.value_or(0));
+ }
+ return color;
+}
+
+bool LightInputMapper::setLightPlayerId(int32_t lightId, int32_t playerId) {
+ auto it = mLights.find(lightId);
+ if (it == mLights.end()) {
+ return false;
+ }
+ auto& light = it->second;
+ return light->setLightPlayerId(playerId);
+}
+
+std::optional<int32_t> LightInputMapper::getLightPlayerId(int32_t lightId) {
+ auto it = mLights.find(lightId);
+ if (it == mLights.end()) {
+ return std::nullopt;
+ }
+ auto& light = it->second;
+ return light->getLightPlayerId();
+}
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/LightInputMapper.h b/services/inputflinger/reader/mapper/LightInputMapper.h
new file mode 100644
index 0000000..43141b8
--- /dev/null
+++ b/services/inputflinger/reader/mapper/LightInputMapper.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _UI_INPUTREADER_LIGHT_INPUT_MAPPER_H
+#define _UI_INPUTREADER_LIGHT_INPUT_MAPPER_H
+
+#include "InputMapper.h"
+
+namespace android {
+
+class LightInputMapper : public InputMapper {
+ // Refer to https://developer.android.com/reference/kotlin/android/graphics/Color
+ /* Number of colors : {red, green, blue} */
+ static constexpr size_t COLOR_NUM = 3;
+ static constexpr int32_t MAX_BRIGHTNESS = 0xff;
+
+public:
+ explicit LightInputMapper(InputDeviceContext& deviceContext);
+ ~LightInputMapper() override;
+
+ uint32_t getSources() override;
+ void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
+ void dump(std::string& dump) override;
+ void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) override;
+ void reset(nsecs_t when) override;
+ void process(const RawEvent* rawEvent) override;
+ bool setLightColor(int32_t lightId, int32_t color) override;
+ bool setLightPlayerId(int32_t lightId, int32_t playerId) override;
+ std::optional<int32_t> getLightColor(int32_t lightId) override;
+ std::optional<int32_t> getLightPlayerId(int32_t lightId) override;
+
+private:
+ struct Light {
+ explicit Light(InputDeviceContext& context, const std::string& name, int32_t id,
+ InputDeviceLightType type)
+ : context(context), name(name), id(id), type(type) {}
+ virtual ~Light() {}
+ InputDeviceContext& context;
+ std::string name;
+ int32_t id;
+ InputDeviceLightType type;
+
+ virtual bool setLightColor(int32_t color) { return false; }
+ virtual std::optional<int32_t> getLightColor() { return std::nullopt; }
+ virtual bool setLightPlayerId(int32_t playerId) { return false; }
+ virtual std::optional<int32_t> getLightPlayerId() { return std::nullopt; }
+
+ virtual void dump(std::string& dump) {}
+
+ std::optional<std::int32_t> getRawLightBrightness(int32_t rawLightId);
+ void setRawLightBrightness(int32_t rawLightId, int32_t brightness);
+ };
+
+ struct SingleLight : public Light {
+ 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;
+
+ bool setLightColor(int32_t color) override;
+ std::optional<int32_t> getLightColor() override;
+ void dump(std::string& dump) override;
+ };
+
+ struct RgbLight : public Light {
+ explicit RgbLight(InputDeviceContext& context, int32_t id,
+ const std::unordered_map<LightColor, int32_t>& rawRgbIds,
+ std::optional<int32_t> rawGlobalId)
+ : Light(context, "RGB", id, InputDeviceLightType::RGB),
+ rawRgbIds(rawRgbIds),
+ rawGlobalId(rawGlobalId) {
+ brightness = rawGlobalId.has_value()
+ ? getRawLightBrightness(rawGlobalId.value()).value_or(MAX_BRIGHTNESS)
+ : MAX_BRIGHTNESS;
+ }
+ // Map from color to raw light id.
+ std::unordered_map<LightColor, int32_t /* rawLightId */> rawRgbIds;
+ // Optional global control raw light id.
+ std::optional<int32_t> rawGlobalId;
+ int32_t brightness;
+
+ bool setLightColor(int32_t color) override;
+ std::optional<int32_t> getLightColor() override;
+ void dump(std::string& dump) override;
+ };
+
+ struct MultiColorLight : public Light {
+ 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;
+
+ bool setLightColor(int32_t color) override;
+ std::optional<int32_t> getLightColor() override;
+ void dump(std::string& dump) override;
+ };
+
+ struct PlayerIdLight : public Light {
+ 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
+ std::unordered_map<int32_t, int32_t> rawLightIds;
+
+ bool setLightPlayerId(int32_t palyerId) override;
+ std::optional<int32_t> getLightPlayerId() override;
+ void dump(std::string& dump) override;
+ };
+
+ int32_t mNextId = 0;
+
+ // Light color map from light color to the color index.
+ static const std::unordered_map<std::string, size_t> LIGHT_COLORS;
+
+ // Light map from light ID to Light
+ std::unordered_map<int32_t, std::unique_ptr<Light>> mLights;
+};
+
+} // namespace android
+
+#endif // _UI_INPUTREADER_LIGHT_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 594ff42..e9d0189 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -87,11 +87,11 @@
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 @@
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 7a77b12..e0c9404 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -42,7 +42,7 @@
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 a86443d..5344227 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -59,27 +59,27 @@
}
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 d1df37b..16cf010 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -1016,7 +1016,8 @@
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 @@
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 @@
RawState* next = &mRawStatesPending.back();
next->clear();
next->when = when;
+ next->readTime = readTime;
// Sync button state.
next->buttonState =
@@ -1453,7 +1455,7 @@
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 @@
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 @@
#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::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 @@
// 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 @@
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 @@
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 @@
}
// 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 @@
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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
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 @@
// 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 @@
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::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::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 @@
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::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 @@
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::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 @@
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::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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
}
// 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 @@
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::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 @@
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 @@
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 6621825..cb52e2d 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -150,7 +150,7 @@
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 @@
struct RawState {
nsecs_t when;
+ nsecs_t readTime;
// Raw pointer sample data.
RawPointerData rawPointerData;
@@ -310,6 +311,7 @@
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 @@
void clear() {
when = 0;
+ readTime = 0;
rawPointerData.clear();
buttonState = 0;
rawVScroll = 0;
@@ -702,39 +705,42 @@
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 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, 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 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 @@
// 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 f58b628..c0ada9d 100644
--- a/services/inputflinger/tests/InputClassifierConverter_test.cpp
+++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp
@@ -38,13 +38,13 @@
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 ab74a04..a72df01 100644
--- a/services/inputflinger/tests/InputClassifier_test.cpp
+++ b/services/inputflinger/tests/InputClassifier_test.cpp
@@ -41,13 +41,13 @@
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_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 209639c..7ad5152 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1232,9 +1232,9 @@
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;
}
@@ -1261,7 +1261,7 @@
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 409c62a..d69bb6a 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -22,6 +22,7 @@
#include <InputReaderBase.h>
#include <InputReaderFactory.h>
#include <KeyboardInputMapper.h>
+#include <LightInputMapper.h>
#include <MultiTouchInputMapper.h>
#include <SensorInputMapper.h>
#include <SingleTouchInputMapper.h>
@@ -36,6 +37,7 @@
#include <math.h>
#include <memory>
+#include <regex>
#include "input/DisplayViewport.h"
#include "input/Input.h"
@@ -48,7 +50,8 @@
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;
@@ -70,6 +73,9 @@
static constexpr int32_t THIRD_TRACKING_ID = 2;
static constexpr int32_t BATTERY_STATUS = 4;
static constexpr int32_t BATTERY_CAPACITY = 66;
+static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
+static constexpr int32_t LIGHT_COLOR = 0x7F448866;
+static constexpr int32_t LIGHT_PLAYER_ID = 2;
// Error tolerance for floating point assertions.
static const float EPSILON = 0.001f;
@@ -83,6 +89,10 @@
return (x + y) / 2;
}
+// Mapping for light color name and the light color
+const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
+ {"green", LightColor::GREEN},
+ {"blue", LightColor::BLUE}};
// --- FakePointerController ---
@@ -412,6 +422,12 @@
std::vector<RawEvent> mEvents GUARDED_BY(mLock);
std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
std::vector<int32_t> mVibrators = {0, 1};
+ std::unordered_map<int32_t, RawLightInfo> mRawLightInfos;
+ // Simulates a device light brightness, from light id to light brightness.
+ std::unordered_map<int32_t /* lightId */, int32_t /* brightness*/> mLightBrightness;
+ // Simulates a device light intensities, from light id to light intensities map.
+ std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>>
+ mLightIntensities;
public:
virtual ~FakeEventHub() {
@@ -427,14 +443,14 @@
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) {
@@ -475,7 +491,7 @@
}
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) {
@@ -562,6 +578,19 @@
device->mscBitmask.loadFromBuffer(buffer);
}
+ void addRawLightInfo(int32_t rawId, RawLightInfo&& info) {
+ mRawLightInfos.emplace(rawId, std::move(info));
+ }
+
+ void fakeLightBrightness(int32_t rawId, int32_t brightness) {
+ mLightBrightness.emplace(rawId, brightness);
+ }
+
+ void fakeLightIntensities(int32_t rawId,
+ const std::unordered_map<LightColor, int32_t> intensities) {
+ mLightIntensities.emplace(rawId, std::move(intensities));
+ }
+
bool getLedState(int32_t deviceId, int32_t led) {
Device* device = getDevice(deviceId);
return device->leds.valueFor(led);
@@ -576,11 +605,12 @@
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;
@@ -869,6 +899,48 @@
std::optional<int32_t> getBatteryStatus(int32_t) const override { return BATTERY_STATUS; }
+ const std::vector<int32_t> getRawLightIds(int32_t deviceId) override {
+ std::vector<int32_t> ids;
+ for (const auto& [rawId, info] : mRawLightInfos) {
+ ids.push_back(rawId);
+ }
+ return ids;
+ }
+
+ std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override {
+ auto it = mRawLightInfos.find(lightId);
+ if (it == mRawLightInfos.end()) {
+ return std::nullopt;
+ }
+ return it->second;
+ }
+
+ void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override {
+ mLightBrightness.emplace(lightId, brightness);
+ }
+
+ void setLightIntensities(int32_t deviceId, int32_t lightId,
+ std::unordered_map<LightColor, int32_t> intensities) override {
+ mLightIntensities.emplace(lightId, intensities);
+ };
+
+ std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override {
+ auto lightIt = mLightBrightness.find(lightId);
+ if (lightIt == mLightBrightness.end()) {
+ return std::nullopt;
+ }
+ return lightIt->second;
+ }
+
+ std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
+ int32_t deviceId, int32_t lightId) override {
+ auto lightIt = mLightIntensities.find(lightId);
+ if (lightIt == mLightIntensities.end()) {
+ return std::nullopt;
+ }
+ return lightIt->second;
+ };
+
virtual bool isExternal(int32_t) const {
return false;
}
@@ -1704,18 +1776,21 @@
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);
@@ -1976,6 +2051,49 @@
ASSERT_EQ(mReader->getBatteryStatus(deviceId), BATTERY_STATUS);
}
+class FakeLightInputMapper : public FakeInputMapper {
+public:
+ FakeLightInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+ : FakeInputMapper(deviceContext, sources) {}
+
+ bool setLightColor(int32_t lightId, int32_t color) override {
+ getDeviceContext().setLightBrightness(lightId, color >> 24);
+ return true;
+ }
+
+ std::optional<int32_t> getLightColor(int32_t lightId) override {
+ std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
+ if (!result.has_value()) {
+ return std::nullopt;
+ }
+ return result.value() << 24;
+ }
+};
+
+TEST_F(InputReaderTest, LightGetColor) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeLightInputMapper& mapper =
+ device->addMapper<FakeLightInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+ RawLightInfo info = {.id = 1,
+ .name = "Mono",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(1 /* rawId */, std::move(info));
+ mFakeEventHub->fakeLightBrightness(1 /* rawId */, 0x55);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_TRUE(mReader->setLightColor(deviceId, 1 /* lightId */, LIGHT_BRIGHTNESS));
+ ASSERT_EQ(mReader->getLightColor(deviceId, 1 /* lightId */), LIGHT_BRIGHTNESS);
+}
+
// --- InputReaderIntegrationTest ---
// These tests create and interact with the InputReader only through its interface.
@@ -2080,12 +2198,14 @@
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);
}
/**
@@ -2562,9 +2682,11 @@
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;
@@ -2643,10 +2765,10 @@
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));
@@ -2816,11 +2938,11 @@
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,
@@ -2846,11 +2968,11 @@
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,
@@ -2883,14 +3005,136 @@
BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
ASSERT_TRUE(mapper.getBatteryCapacity());
- ASSERT_EQ(*mapper.getBatteryCapacity(), BATTERY_CAPACITY);
+ ASSERT_EQ(mapper.getBatteryCapacity().value_or(-1), BATTERY_CAPACITY);
}
TEST_F(BatteryInputMapperTest, GetBatteryStatus) {
BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
ASSERT_TRUE(mapper.getBatteryStatus());
- ASSERT_EQ(*mapper.getBatteryStatus(), BATTERY_STATUS);
+ ASSERT_EQ(mapper.getBatteryStatus().value_or(-1), BATTERY_STATUS);
+}
+
+// --- LightInputMapperTest ---
+class LightInputMapperTest : public InputMapperTest {
+protected:
+ void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT); }
+};
+
+TEST_F(LightInputMapperTest, GetSources) {
+ LightInputMapper& mapper = addMapperAndConfigure<LightInputMapper>();
+
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
+}
+
+TEST_F(LightInputMapperTest, SingleLight) {
+ RawLightInfo infoSingle = {.id = 1,
+ .name = "Mono",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(infoSingle.id, std::move(infoSingle));
+
+ LightInputMapper& mapper = addMapperAndConfigure<LightInputMapper>();
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ const auto& ids = info.getLightIds();
+ ASSERT_EQ(1UL, ids.size());
+ ASSERT_EQ(InputDeviceLightType::SINGLE, info.getLightInfo(ids[0])->type);
+
+ ASSERT_TRUE(mapper.setLightColor(ids[0], LIGHT_BRIGHTNESS));
+ ASSERT_EQ(mapper.getLightColor(ids[0]).value_or(-1), LIGHT_BRIGHTNESS);
+}
+
+TEST_F(LightInputMapperTest, RGBLight) {
+ RawLightInfo infoRed = {.id = 1,
+ .name = "red",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
+ .path = ""};
+ RawLightInfo infoGreen = {.id = 2,
+ .name = "green",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
+ .path = ""};
+ RawLightInfo infoBlue = {.id = 3,
+ .name = "blue",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
+ mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
+ mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
+
+ LightInputMapper& mapper = addMapperAndConfigure<LightInputMapper>();
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ const auto& ids = info.getLightIds();
+ ASSERT_EQ(1UL, ids.size());
+ ASSERT_EQ(InputDeviceLightType::RGB, info.getLightInfo(ids[0])->type);
+
+ ASSERT_TRUE(mapper.setLightColor(ids[0], LIGHT_COLOR));
+ ASSERT_EQ(mapper.getLightColor(ids[0]).value_or(-1), LIGHT_COLOR);
+}
+
+TEST_F(LightInputMapperTest, MultiColorRGBLight) {
+ RawLightInfo infoColor = {.id = 1,
+ .name = "red",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS |
+ InputLightClass::MULTI_INTENSITY |
+ InputLightClass::MULTI_INDEX,
+ .path = ""};
+
+ mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
+
+ LightInputMapper& mapper = addMapperAndConfigure<LightInputMapper>();
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ const auto& ids = info.getLightIds();
+ ASSERT_EQ(1UL, ids.size());
+ ASSERT_EQ(InputDeviceLightType::MULTI_COLOR, info.getLightInfo(ids[0])->type);
+
+ ASSERT_TRUE(mapper.setLightColor(ids[0], LIGHT_COLOR));
+ ASSERT_EQ(mapper.getLightColor(ids[0]).value_or(-1), LIGHT_COLOR);
+}
+
+TEST_F(LightInputMapperTest, PlayerIdLight) {
+ RawLightInfo info1 = {.id = 1,
+ .name = "player1",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ RawLightInfo info2 = {.id = 2,
+ .name = "player2",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ RawLightInfo info3 = {.id = 3,
+ .name = "player3",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ RawLightInfo info4 = {.id = 4,
+ .name = "player4",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
+ mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
+ mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
+ mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
+
+ LightInputMapper& mapper = addMapperAndConfigure<LightInputMapper>();
+ InputDeviceInfo info;
+ mapper.populateDeviceInfo(&info);
+ const auto& ids = info.getLightIds();
+ ASSERT_EQ(1UL, ids.size());
+ ASSERT_EQ(InputDeviceLightType::PLAYER_ID, info.getLightInfo(ids[0])->type);
+
+ ASSERT_FALSE(mapper.setLightColor(ids[0], LIGHT_COLOR));
+ ASSERT_TRUE(mapper.setLightPlayerId(ids[0], LIGHT_PLAYER_ID));
+ ASSERT_EQ(mapper.getLightPlayerId(ids[0]).value_or(-1), LIGHT_PLAYER_ID);
}
// --- KeyboardInputMapperTest ---
@@ -2919,14 +3163,14 @@
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);
@@ -2959,7 +3203,7 @@
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);
@@ -2974,7 +3218,7 @@
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);
@@ -2988,8 +3232,8 @@
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);
@@ -3003,8 +3247,8 @@
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);
@@ -3018,8 +3262,8 @@
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);
@@ -3033,8 +3277,8 @@
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);
@@ -3048,6 +3292,28 @@
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);
@@ -3064,7 +3330,7 @@
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);
@@ -3072,19 +3338,19 @@
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());
@@ -3171,7 +3437,7 @@
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);
@@ -3179,7 +3445,7 @@
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);
@@ -3197,16 +3463,16 @@
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);
}
@@ -3227,9 +3493,9 @@
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);
@@ -3237,9 +3503,9 @@
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);
}
@@ -3303,48 +3569,48 @@
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));
@@ -3372,7 +3638,7 @@
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());
@@ -3380,7 +3646,7 @@
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());
@@ -3487,20 +3753,20 @@
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());
@@ -3555,28 +3821,28 @@
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);
}
@@ -3593,28 +3859,28 @@
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);
}
@@ -3652,9 +3918,9 @@
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],
@@ -3735,8 +4001,8 @@
// 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);
@@ -3776,8 +4042,8 @@
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);
@@ -3824,16 +4090,16 @@
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],
@@ -3847,8 +4113,8 @@
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],
@@ -3860,8 +4126,8 @@
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],
@@ -3880,10 +4146,10 @@
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],
@@ -3897,9 +4163,9 @@
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],
@@ -3907,8 +4173,8 @@
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],
@@ -3993,8 +4259,8 @@
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);
@@ -4009,8 +4275,8 @@
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);
@@ -4033,9 +4299,9 @@
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,
@@ -4062,8 +4328,8 @@
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);
@@ -4078,16 +4344,16 @@
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);
@@ -4104,8 +4370,8 @@
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);
@@ -4124,8 +4390,8 @@
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);
@@ -4145,8 +4411,8 @@
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);
@@ -4165,8 +4431,8 @@
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);
@@ -4186,8 +4452,8 @@
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);
@@ -4206,8 +4472,8 @@
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);
@@ -4227,8 +4493,8 @@
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);
@@ -4247,8 +4513,8 @@
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);
@@ -4278,9 +4544,9 @@
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);
@@ -4306,9 +4572,9 @@
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);
@@ -4317,8 +4583,8 @@
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);
@@ -4331,8 +4597,8 @@
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);
@@ -4345,9 +4611,9 @@
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);
@@ -4366,9 +4632,9 @@
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);
@@ -4394,9 +4660,9 @@
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);
@@ -4619,46 +4885,46 @@
}
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) {
@@ -5946,64 +6212,64 @@
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) {
@@ -7437,6 +7703,32 @@
}
/**
+ * 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/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
index a5be01c..2ae49fa 100644
--- a/services/surfaceflinger/ClientCache.cpp
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -25,6 +25,8 @@
namespace android {
+using base::StringAppendF;
+
ANDROID_SINGLETON_STATIC_INSTANCE(ClientCache);
ClientCache::ClientCache() : mDeathRecipient(new CacheDeathRecipient) {}
@@ -203,4 +205,18 @@
ClientCache::getInstance().removeProcess(who);
}
+void ClientCache::dump(std::string& result) {
+ std::lock_guard lock(mMutex);
+ for (auto i : mBuffers) {
+ const sp<IBinder>& cacheOwner = i.second.first;
+ StringAppendF(&result," Cache owner: %p\n", cacheOwner.get());
+ auto &buffers = i.second.second;
+ for (auto& [id, clientCacheBuffer] : buffers) {
+ StringAppendF(&result, "\t ID: %d, Width/Height: %d,%d\n", (int)id,
+ (int)clientCacheBuffer.buffer->getWidth(),
+ (int)clientCacheBuffer.buffer->getHeight());
+ }
+ }
+}
+
}; // namespace android
diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h
index d7af7c0..0d597c8 100644
--- a/services/surfaceflinger/ClientCache.h
+++ b/services/surfaceflinger/ClientCache.h
@@ -53,6 +53,8 @@
void unregisterErasedRecipient(const client_cache_t& cacheId,
const wp<ErasedRecipient>& recipient);
+ void dump(std::string& result);
+
private:
std::mutex mMutex;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
index 782c8d7..6b9597b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
@@ -24,6 +24,7 @@
#include <ui/FloatRect.h>
#include <ui/Rect.h>
#include <ui/Region.h>
+#include <ui/StretchEffect.h>
#include <ui/Transform.h>
namespace android::compositionengine::impl {
@@ -58,5 +59,6 @@
void dumpVal(std::string& out, const char* name, const ui::Size&);
void dumpVal(std::string& out, const char* name, const mat4& tr);
+void dumpVal(std::string& out, const char* name, const StretchEffect&);
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
index 9d1bb02..0cc2c6e 100644
--- a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
@@ -100,4 +100,10 @@
); /* clang-format on */
}
+void dumpVal(std::string& out, const char* name, const StretchEffect& effect) {
+ StringAppendF(&out, "%s={ area=[%f, %f, %f, %f], vec=(%f, %f), max=%f } ", name,
+ effect.area.left, effect.area.top, effect.area.right, effect.area.bottom,
+ effect.vectorX, effect.vectorY, effect.maxAmount);
+}
+
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
index 1338538..430945a 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
@@ -74,6 +74,9 @@
dumpVal(out, "blend", toString(blendMode), blendMode);
dumpVal(out, "alpha", alpha);
dumpVal(out, "backgroundBlurRadius", backgroundBlurRadius);
+ if (stretchEffect.hasEffect()) {
+ dumpVal(out, "stretchEffect", stretchEffect);
+ }
if (!metadata.empty()) {
out.append("\n metadata {");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6a03996..141a112 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -489,7 +489,7 @@
compositionState->alpha = alpha;
compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
compositionState->blurRegions = drawingState.blurRegions;
- compositionState->stretchEffect = drawingState.stretchEffect;
+ compositionState->stretchEffect = getStretchEffect();
}
void Layer::prepareGeometryCompositionState() {
@@ -559,7 +559,7 @@
// Force client composition for special cases known only to the front-end.
if (isHdrY410() || usesRoundedCorners || drawShadows() || drawingState.blurRegions.size() > 0 ||
- drawingState.stretchEffect.hasEffect()) {
+ compositionState->stretchEffect.hasEffect()) {
compositionState->forceClientComposition = true;
}
}
@@ -1437,6 +1437,22 @@
return true;
}
+StretchEffect Layer::getStretchEffect() const {
+ if (mDrawingState.stretchEffect.hasEffect()) {
+ return mDrawingState.stretchEffect;
+ }
+
+ sp<Layer> parent = getParent();
+ if (parent != nullptr) {
+ auto effect = parent->getStretchEffect();
+ if (effect.hasEffect()) {
+ // TODO(b/179047472): Map it? Or do we make the effect be in global space?
+ return effect;
+ }
+ }
+ return StretchEffect{};
+}
+
void Layer::updateTreeHasFrameRateVote() {
const auto traverseTree = [&](const LayerVector::Visitor& visitor) {
auto parent = getParent();
@@ -1452,7 +1468,7 @@
// First traverse the tree and count how many layers has votes. In addition
// activate the layers in Scheduler's LayerHistory for it to check for changes
int layersWithVote = 0;
- traverseTree([&layersWithVote, this](Layer* layer) {
+ traverseTree([&layersWithVote](Layer* layer) {
const auto layerVotedWithDefaultCompatibility =
layer->mCurrentState.frameRate.rate.isValid() &&
layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default;
@@ -1468,20 +1484,21 @@
layerVotedWithExactCompatibility) {
layersWithVote++;
}
-
- mFlinger->mScheduler->recordLayerHistory(layer, systemTime(),
- LayerHistory::LayerUpdateType::SetFrameRate);
});
// Now update the other layers
bool transactionNeeded = false;
- traverseTree([layersWithVote, &transactionNeeded](Layer* layer) {
- if (layer->mCurrentState.treeHasFrameRateVote != layersWithVote > 0) {
+ traverseTree([layersWithVote, &transactionNeeded, this](Layer* layer) {
+ const bool treeHasFrameRateVote = layersWithVote > 0;
+ if (layer->mCurrentState.treeHasFrameRateVote != treeHasFrameRateVote) {
layer->mCurrentState.sequence++;
- layer->mCurrentState.treeHasFrameRateVote = layersWithVote > 0;
+ layer->mCurrentState.treeHasFrameRateVote = treeHasFrameRateVote;
layer->mCurrentState.modified = true;
layer->setTransactionFlags(eTransactionNeeded);
transactionNeeded = true;
+
+ mFlinger->mScheduler->recordLayerHistory(layer, systemTime(),
+ LayerHistory::LayerUpdateType::SetFrameRate);
}
});
@@ -1742,6 +1759,7 @@
info.mRefreshPending = isBufferLatched();
info.mIsOpaque = isOpaque(ds);
info.mContentDirty = contentDirty;
+ info.mStretchEffect = getStretchEffect();
return info;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1461756..14bb5b7 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -943,6 +943,7 @@
bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; }
bool setStretchEffect(const StretchEffect& effect);
+ StretchEffect getStretchEffect() const;
protected:
class SyncPoint {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index da8360e..7e41915 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -254,6 +254,11 @@
std::function<void()> mCallback;
};
+enum Permission {
+ ACCESS_SURFACE_FLINGER = 0x1,
+ ROTATE_SURFACE_FLINGER = 0x2,
+};
+
} // namespace anonymous
struct SetInputWindowsListener : os::BnSetInputWindowsListener {
@@ -966,9 +971,18 @@
}
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 +1257,6 @@
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 +1267,6 @@
}));
}
-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)) {
@@ -3313,7 +3288,7 @@
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 +3361,23 @@
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
+ 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();
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPid = ipc->getCallingPid();
+ const int originUid = ipc->getCallingUid();
+
{
Mutex::Autolock _l(mQueueLock);
-
- const int64_t postTime = systemTime();
- bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPid = ipc->getCallingPid();
- const int originUid = ipc->getCallingUid();
-
// 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 +3412,7 @@
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 +3426,8 @@
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 +3482,11 @@
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 +3504,7 @@
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 +3524,7 @@
}
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 +3628,10 @@
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 +3756,8 @@
// 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) {
@@ -4812,6 +4794,8 @@
getRenderEngine().dump(result);
+ result.append("ClientCache state:\n");
+ ClientCache::getInstance().dump(result);
DebugEGLImageTracker::getInstance()->dump(result);
if (const auto display = getDefaultDisplayDeviceLocked()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 21cd2a5..1cb1630 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -344,7 +344,8 @@
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 +442,7 @@
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 +455,7 @@
isAutoTimestamp(isAutoTimestamp),
buffer(uncacheBuffer),
postTime(postTime),
- privileged(privileged),
+ permissions(permissions),
hasListenerCallbacks(hasListenerCallbacks),
listenerCallbacks(listenerCallbacks),
originPid(originPid),
@@ -471,7 +472,7 @@
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 +562,7 @@
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;
@@ -740,7 +737,7 @@
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);
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 61005c9..b0413f1 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -499,6 +499,9 @@
if (state.what & layer_state_t::eShadowRadiusChanged) {
addShadowRadiusLocked(transaction, layerId, state.shadowRadius);
}
+ if (state.what & layer_state_t::eStretchChanged) {
+ ALOGW("SurfaceInterceptor not implemented for eStretchChanged");
+ }
}
void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index a6d07d0..5c8c2d8 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -81,7 +81,7 @@
std::string name() override { return "BufferStateLayer"; }
sp<Layer> createLayer(TestableSurfaceFlinger& flinger) override {
sp<Client> client;
- LayerCreationArgs args(flinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT,
+ LayerCreationArgs args(flinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT,
LAYER_FLAGS, LayerMetadata());
return new BufferStateLayer(args);
}
@@ -188,7 +188,8 @@
.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));
+ std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr,
+ /*hasMultipleModes*/ true);
}
void SetFrameRateTest::setupComposer(uint32_t virtualDisplayCount) {
@@ -488,5 +489,28 @@
EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, ""));
}
+TEST_P(SetFrameRateTest, SetOnParentActivatesTree) {
+ const auto& layerFactory = GetParam();
+
+ auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
+ if (!parent->isVisible()) {
+ // This is a hack as all the test layers except EffectLayer are not visible,
+ // but since the logic is unified in Layer, it should be fine.
+ return;
+ }
+
+ auto child = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
+ addChild(parent, child);
+
+ parent->setFrameRate(FRAME_RATE_VOTE1);
+ commitTransaction();
+
+ const auto layerHistorySummary =
+ mFlinger.mutableScheduler().mutableLayerHistory()->summarize(0);
+ ASSERT_EQ(2u, layerHistorySummary.size());
+ EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[0].desiredRefreshRate));
+ EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[1].desiredRefreshRate));
+}
+
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 2ba6490..63baf7d 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -246,6 +246,8 @@
void resetScheduler(Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); }
+ TestableScheduler& mutableScheduler() const { return *mScheduler; }
+
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
mFactory.mCreateBufferQueue = f;
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 2d4690a..d1cd397 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 @@
// 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 @@
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;
+ static constexpr int kFixedRangeBeginInclusive = 0;
+ static constexpr int kFixedRangeEndInclusive = 9;
- if (strncmp(key, prefix, prefix_len) || val[0] == '\0')
- return;
- key += prefix_len;
+ bool logged = false;
- // debug.vulkan.layer.<priority>
- int priority = -1;
- if (key[0] >= '0' && key[0] <= '9')
- priority = atoi(key);
+ 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 (priority < 0) {
- ALOGW("Ignored implicit layer %s with invalid priority %s", val,
- key);
- return;
+ 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;
+ }
+
+ ++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) {