Add an InputClassifier HAL
The new HAL will be responsible for processing touch video frames that
are received from InputClassifier stage.
After processing, the HAL will generate a classification of the current
gesture. This classification will later be provided to the app via
the MotionEvent.getClassification() public API.
The eventual goal is to classify each event stream as a force touch
or not a force touch.
An example implementation of the HAL is presented here. This code was
used for local testing on blueline, and should not be actually installed
or used in any way other than for reference.
Bug: 62940136
Test: observed "detected deep press" logs when pressing with large
finger area on the touchscreen
Change-Id: Id6ac4337435e4ac07877da11ca184b6dd4d64780
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index d4c422d..123aae5 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -240,6 +240,14 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.input.classifier</name>
+ <version>1.0</version>
+ <interface>
+ <name>IInputClassifier</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="false">
<name>android.hardware.keymaster</name>
<version>3.0</version>
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
new file mode 100644
index 0000000..c3c6fc6
--- /dev/null
+++ b/input/classifier/1.0/Android.bp
@@ -0,0 +1,35 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.input.classifier@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IInputClassifier.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "Action",
+ "Axis",
+ "Button",
+ "Classification",
+ "EdgeFlag",
+ "Flag",
+ "Meta",
+ "MotionEvent",
+ "PointerCoords",
+ "PointerProperties",
+ "PolicyFlag",
+ "Source",
+ "SourceClass",
+ "ToolType",
+ "VideoFrame",
+ ],
+ gen_java: true,
+}
+
diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal
new file mode 100644
index 0000000..edc1138
--- /dev/null
+++ b/input/classifier/1.0/IInputClassifier.hal
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.classifier@1.0;
+
+interface IInputClassifier {
+
+ /**
+ * Returns the classification for the current sequence of input events.
+ */
+ classify(MotionEvent event) generates (Classification classification);
+
+};
diff --git a/input/classifier/1.0/default/Android.bp b/input/classifier/1.0/default/Android.bp
new file mode 100644
index 0000000..ddd883c
--- /dev/null
+++ b/input/classifier/1.0/default/Android.bp
@@ -0,0 +1,23 @@
+cc_binary {
+ name: "android.hardware.input.classifier@1.0-service-example",
+ init_rc: ["android.hardware.input.classifier@1.0-service-example.rc"],
+ relative_install_path: "hw",
+ vendor: true,
+ vintf_fragments: ["manifest_input.classifier.xml"],
+ srcs: [
+ "InputClassifier.cpp",
+ "service.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.input.classifier@1.0",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp
new file mode 100644
index 0000000..c463361
--- /dev/null
+++ b/input/classifier/1.0/default/InputClassifier.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputClassifierHAL"
+
+#include "InputClassifier.h"
+#include <inttypes.h>
+#include <log/log.h>
+#include <utils/Timers.h>
+
+using namespace android::hardware::input::classifier::V1_0;
+
+namespace android {
+namespace hardware {
+namespace input {
+namespace classifier {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
+Return<Classification> InputClassifier::classify(const MotionEvent& event) {
+ /**
+ * In this example implementation, we will see how many "pixels" inside the video frame
+ * exceed the value of 250. If more than 6 such pixels are present, then treat the event
+ * as a "DEEP_PRESS".
+ */
+ if (event.frames.size() == 0) {
+ return Classification::NONE;
+ }
+ ALOGI("Frame(O) timestamp = %" PRIu64 ", received %zu frame(s)", event.frames[0].timestamp,
+ event.frames.size());
+ for (const VideoFrame& frame : event.frames) {
+ size_t count = 0;
+ for (size_t i = 0; i < frame.data.size(); i++) {
+ if (frame.data[i] > 250) {
+ count++;
+ }
+ }
+ if (count > 6) {
+ return Classification::DEEP_PRESS;
+ }
+ }
+
+ return Classification::NONE;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace classifier
+} // namespace input
+} // namespace hardware
+} // namespace android
diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h
new file mode 100644
index 0000000..0858ecb
--- /dev/null
+++ b/input/classifier/1.0/default/InputClassifier.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
+#define ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
+
+#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace input {
+namespace classifier {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+
+struct InputClassifier : public IInputClassifier {
+ // Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
+ Return<Classification> classify(
+ const ::android::hardware::input::classifier::V1_0::MotionEvent& event) override;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace classifier
+} // namespace input
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
diff --git a/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc
new file mode 100644
index 0000000..f799bf4
--- /dev/null
+++ b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc
@@ -0,0 +1,9 @@
+service vendor.input.classifier-1-0 /vendor/bin/hw/android.hardware.input.classifier@1.0-service-example
+ # Must be specified if "disabled" is set. This HAL will only start if requested via getService
+ interface android.hardware.input.classifier@1.0::IInputClassifier default
+ class hal
+ user nobody
+ # will not be restarted if it exits until it is requested to be restarted
+ oneshot
+ # will only be started when requested
+ disabled
diff --git a/input/classifier/1.0/default/manifest_input.classifier.xml b/input/classifier/1.0/default/manifest_input.classifier.xml
new file mode 100644
index 0000000..8634169
--- /dev/null
+++ b/input/classifier/1.0/default/manifest_input.classifier.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.input.classifier</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IInputClassifier</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/input/classifier/1.0/default/service.cpp b/input/classifier/1.0/default/service.cpp
new file mode 100644
index 0000000..6ef2118
--- /dev/null
+++ b/input/classifier/1.0/default/service.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.input.classifier@1.0"
+
+#include <inttypes.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+#include "InputClassifier.h"
+#include "android/hardware/input/classifier/1.0/IInputClassifier.h"
+
+using android::sp;
+using android::status_t;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::input::classifier::V1_0::IInputClassifier;
+using android::hardware::input::classifier::V1_0::implementation::InputClassifier;
+
+int main() {
+ sp<IInputClassifier> classifier = new InputClassifier();
+
+ configureRpcThreadpool(1, true);
+ const status_t status = classifier->registerAsService();
+
+ if (status != android::OK) {
+ ALOGE("Could not register InputClassifier HAL!");
+ return EXIT_FAILURE; // or handle error
+ }
+
+ joinRpcThreadpool();
+ LOG_ALWAYS_FATAL("Under normal operation, joinRpcThreadpool should never return");
+ return EXIT_FAILURE;
+}
diff --git a/input/classifier/1.0/types.hal b/input/classifier/1.0/types.hal
new file mode 100644
index 0000000..244ecd9
--- /dev/null
+++ b/input/classifier/1.0/types.hal
@@ -0,0 +1,829 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.classifier@1.0;
+
+
+/**
+ * Constants that identify each individual axis of a motion event.
+ */
+enum Axis : uint64_t {
+ /**
+ * Axis constant: X axis of a motion event.
+ *
+ * - For a touch screen, reports the absolute X screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * - For a touch pad, reports the absolute X surface position of the center of the touch
+ * contact area. The units are device-dependent.
+ * - For a mouse, reports the absolute X screen position of the mouse pointer.
+ * The units are display pixels.
+ * - For a trackball, reports the relative horizontal displacement of the trackball.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * - For a joystick, reports the absolute X position of the joystick.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ */
+ X = 0,
+ /**
+ * Axis constant: Y axis of a motion event.
+ *
+ * - For a touch screen, reports the absolute Y screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * - For a touch pad, reports the absolute Y surface position of the center of the touch
+ * contact area. The units are device-dependent.
+ * - For a mouse, reports the absolute Y screen position of the mouse pointer.
+ * The units are display pixels.
+ * - For a trackball, reports the relative vertical displacement of the trackball.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ * - For a joystick, reports the absolute Y position of the joystick.
+ * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+ */
+ Y = 1,
+ /**
+ * Axis constant: Pressure axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the approximate pressure applied to the surface
+ * by a finger or other tool. The value is normalized to a range from
+ * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+ * may be generated depending on the calibration of the input device.
+ * - For a trackball, the value is set to 1 if the trackball button is pressed
+ * or 0 otherwise.
+ * - For a mouse, the value is set to 1 if the primary mouse button is pressed
+ * or 0 otherwise.
+ */
+ PRESSURE = 2,
+ /**
+ * Axis constant: Size axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the approximate size of the contact area in
+ * relation to the maximum detectable size for the device. The value is normalized
+ * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+ * although it is not a linear scale. This value is of limited use.
+ * To obtain calibrated size information, see
+ * {@link TOUCH_MAJOR} or {@link TOOL_MAJOR}.
+ */
+ SIZE = 3,
+ /**
+ * Axis constant: TouchMajor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * - For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent.
+ */
+ TOUCH_MAJOR = 4,
+ /**
+ * Axis constant: TouchMinor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * - For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ */
+ TOUCH_MINOR = 5,
+ /**
+ * Axis constant: ToolMajor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * - For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ *
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ */
+ TOOL_MAJOR = 6,
+ /**
+ * Axis constant: ToolMinor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * - For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ *
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ */
+ TOOL_MINOR = 7,
+ /**
+ * Axis constant: Orientation axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the orientation of the finger
+ * or tool in radians relative to the vertical plane of the device.
+ * An angle of 0 radians indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation. A positive angle
+ * indicates that the major axis of contact is oriented to the right. A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+ * (finger pointing fully right).
+ * - For a stylus, the orientation indicates the direction in which the stylus
+ * is pointing in relation to the vertical axis of the current orientation of the screen.
+ * The range is from -PI radians to PI radians, where 0 is pointing up,
+ * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+ * is pointing right. See also {@link TILT}.
+ */
+ ORIENTATION = 8,
+ /**
+ * Axis constant: Vertical Scroll axis of a motion event.
+ *
+ * - For a mouse, reports the relative movement of the vertical scroll wheel.
+ * The value is normalized to a range from -1.0 (down) to 1.0 (up).
+ *
+ * The framework may use this axis to scroll views vertically.
+ */
+ VSCROLL = 9,
+ /**
+ * Axis constant: Horizontal Scroll axis of a motion event.
+ *
+ * - For a mouse, reports the relative movement of the horizontal scroll wheel.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ *
+ * The framework may use this axis to scroll views horizontally.
+ */
+ HSCROLL = 10,
+ /**
+ * Axis constant: Z axis of a motion event.
+ *
+ * - For a joystick, reports the absolute Z position of the joystick.
+ * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+ * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute X position of the second joystick instead.</em>
+ */
+ Z = 11,
+ /**
+ * Axis constant: X Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the X axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ */
+ RX = 12,
+ /**
+ * Axis constant: Y Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the Y axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ */
+ RY = 13,
+ /**
+ * Axis constant: Z Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the Z axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ * On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute Y position of the second joystick instead.
+ */
+ RZ = 14,
+ /**
+ * Axis constant: Hat X axis of a motion event.
+ *
+ * - For a joystick, reports the absolute X position of the directional hat control.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ */
+ HAT_X = 15,
+ /**
+ * Axis constant: Hat Y axis of a motion event.
+ *
+ * - For a joystick, reports the absolute Y position of the directional hat control.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ */
+ HAT_Y = 16,
+ /**
+ * Axis constant: Left Trigger axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the left trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ */
+ LTRIGGER = 17,
+ /**
+ * Axis constant: Right Trigger axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the right trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ */
+ RTRIGGER = 18,
+ /**
+ * Axis constant: Throttle axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the throttle control.
+ * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+ */
+ THROTTLE = 19,
+ /**
+ * Axis constant: Rudder axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the rudder control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ */
+ RUDDER = 20,
+ /**
+ * Axis constant: Wheel axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the steering wheel control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ */
+ WHEEL = 21,
+ /**
+ * Axis constant: Gas axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the gas (accelerator) control.
+ * The value is normalized to a range from 0.0 (no acceleration)
+ * to 1.0 (maximum acceleration).
+ */
+ GAS = 22,
+ /**
+ * Axis constant: Brake axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the brake control.
+ * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+ */
+ BRAKE = 23,
+ /**
+ * Axis constant: Distance axis of a motion event.
+ *
+ * - For a stylus, reports the distance of the stylus from the screen.
+ * A value of 0.0 indicates direct contact and larger values indicate increasing
+ * distance from the surface.
+ */
+ DISTANCE = 24,
+ /**
+ * Axis constant: Tilt axis of a motion event.
+ *
+ * - For a stylus, reports the tilt angle of the stylus in radians where
+ * 0 radians indicates that the stylus is being held perpendicular to the
+ * surface, and PI/2 radians indicates that the stylus is being held flat
+ * against the surface.
+ */
+ TILT = 25,
+ /**
+ * Axis constant: Generic scroll axis of a motion event.
+ *
+ * - This is used for scroll axis motion events that can't be classified as strictly
+ * vertical or horizontal. The movement of a rotating scroller is an example of this.
+ */
+ SCROLL = 26,
+ /**
+ * Axis constant: The movement of x position of a motion event.
+ *
+ * - For a mouse, reports a difference of x position between the previous position.
+ * This is useful when pointer is captured, in that case the mouse pointer doesn't
+ * change the location but this axis reports the difference which allows the app
+ * to see how the mouse is moved.
+ */
+ RELATIVE_X = 27,
+ /**
+ * Axis constant: The movement of y position of a motion event.
+ *
+ * Same as {@link RELATIVE_X}, but for y position.
+ */
+ RELATIVE_Y = 28,
+ /**
+ * Axis constant: Generic 1 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_1 = 32,
+ /**
+ * Axis constant: Generic 2 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_2 = 33,
+ /**
+ * Axis constant: Generic 3 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_3 = 34,
+ /**
+ * Axis constant: Generic 4 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_4 = 35,
+ /**
+ * Axis constant: Generic 5 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_5 = 36,
+ /**
+ * Axis constant: Generic 6 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_6 = 37,
+ /**
+ * Axis constant: Generic 7 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_7 = 38,
+ /**
+ * Axis constant: Generic 8 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_8 = 39,
+ /**
+ * Axis constant: Generic 9 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_9 = 40,
+ /**
+ * Axis constant: Generic 10 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_10 = 41,
+ /**
+ * Axis constant: Generic 11 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_11 = 42,
+ /**
+ * Axis constant: Generic 12 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_12 = 43,
+ /**
+ * Axis constant: Generic 13 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_13 = 44,
+ /**
+ * Axis constant: Generic 14 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_14 = 45,
+ /**
+ * Axis constant: Generic 15 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_15 = 46,
+ /**
+ * Axis constant: Generic 16 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ GENERIC_16 = 47,
+};
+
+/**
+ * Tool type of a pointer
+ */
+enum ToolType: uint8_t {
+ UNKNOWN = 0,
+ FINGER = 1,
+ STYLUS = 2,
+ MOUSE = 3,
+ ERASER = 4,
+};
+
+/**
+ * Properties of a particular pointer. Analogous to Android's PointerProperties.
+ */
+struct PointerProperties {
+ /**
+ * A number identifying a specific pointer. When a pointer is lifted,
+ * this value may be reused by another new pointer, even during the
+ * same gesture. For example, if there are two pointers touching the screen
+ * at the same time, they might have pointer ID's of 0 and 1. If the
+ * pointer with id = 0 is lifted, while the pointer with id = 1 remains, and
+ * a new pointer is placed on the screen, then the new pointer may receive
+ * an id of 0. While a pointer is active, it is guaranteed to keep the same
+ * id.
+ */
+ int32_t id;
+ /**
+ * Type of tool used to make contact, such as a finger or stylus, if known.
+ */
+ ToolType toolType;
+};
+
+/**
+ * Pointer coordinate data. Analogous to Android's PointerCoords.
+ */
+struct PointerCoords {
+ /**
+ * Bitfield of axes that are present in this structure.
+ */
+ bitfield<Axis> bits;
+ /**
+ * The values corresponding to each non-zero axis. This vector only
+ * contains non-zero entries. If an axis that is not currently specified
+ * in "bits" is requested, a zero value is returned.
+ * There are only as many values stored here
+ * as there are non-zero bits in the "bits" field.
+ * The values are position-packed. So the first non-zero axis will be
+ * at position 0, the next non-zero axis will be at position 1, and so on.
+ */
+ vec<float> values;
+};
+
+enum SourceClass: uint8_t {
+ NONE = 1 << 0,
+ BUTTON = 1 << 1,
+ POINTER = 1 << 2,
+ NAVIGATION = 1 << 3,
+ POSITION = 1 << 4,
+ JOYSTICK = 1 << 5,
+};
+
+/**
+ * Input sources
+ */
+enum Source: uint32_t {
+ UNKNOWN = 0,
+ KEYBOARD = (1 << 8) | SourceClass:BUTTON,
+ DPAD = (1 << 9) | SourceClass:BUTTON,
+ GAMEPAD = (1 << 10) | SourceClass:BUTTON,
+ TOUCHSCREEN = (1 << 12) | SourceClass:POINTER,
+ MOUSE = (1 << 13) | SourceClass:POINTER,
+ STYLUS = (1 << 14) | SourceClass:POINTER,
+ BLUETOOTH_STYLUS = (1 << 15) | STYLUS,
+ TRACKBALL = (1 << 16) | SourceClass:NAVIGATION,
+ MOUSE_RELATIVE = (1 << 17) | SourceClass:NAVIGATION,
+ TOUCHPAD = (1 << 20) | SourceClass:POSITION,
+ TOUCH_NAVIGATION = (1 << 21) | SourceClass:NONE,
+ ROTARY_ENCODER = (1 << 22) | SourceClass:NONE,
+ JOYSTICK = (1 << 24) | SourceClass:JOYSTICK,
+ ANY = 0xFFFFFF00,
+};
+
+/** Motion event actions */
+enum Action: int32_t {
+ /** A pressed gesture has started, the motion contains the initial starting location. */
+ DOWN = 0,
+ /**
+ * A pressed gesture has finished, the motion contains the final release location
+ * as well as any intermediate points since the last down or move event.
+ */
+ UP = 1,
+ /**
+ * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+ * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point.
+ */
+ MOVE = 2,
+ /**
+ * The current gesture has been aborted.
+ * You will not receive any more points in it. You must treat this as
+ * an up event, but not perform any action that you normally would.
+ */
+ CANCEL = 3,
+ /**
+ * A movement has happened outside of the normal bounds of the UI element.
+ * This does not provide a full gesture, but only the initial location of the movement/touch.
+ */
+ OUTSIDE = 4,
+ /**
+ * A non-primary pointer has gone down.
+ */
+ POINTER_DOWN = 5,
+ /**
+ * A non-primary pointer has gone up.
+ */
+ POINTER_UP = 6,
+ /**
+ * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+ * The motion contains the most recent point, as well as any intermediate points since
+ * the last hover move event.
+ */
+ HOVER_MOVE = 7,
+ /**
+ * The motion event contains relative vertical and/or horizontal scroll offsets.
+ * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
+ * and AMOTION_EVENT_AXIS_HSCROLL.
+ * The pointer may or may not be down when this event is dispatched.
+ * The framework will always deliver this action to the window under the pointer, which
+ * may not be the window currently touched.
+ */
+ SCROLL = 8,
+ /**
+ * The pointer is not down but has entered the boundaries of a window or view.
+ */
+ HOVER_ENTER = 9,
+ /**
+ * The pointer is not down but has exited the boundaries of a window or view.
+ */
+ HOVER_EXIT = 10,
+ /**
+ * One or more buttons have been pressed.
+ */
+ BUTTON_PRESS = 11,
+ /**
+ * One or more buttons have been released.
+ */
+ BUTTON_RELEASE = 12,
+};
+
+/** Edge flags */
+enum EdgeFlag : int32_t {
+ /** No edges are intersected */
+ NONE = 0,
+ /** Motion intersected top edge of the screen */
+ TOP = 1 << 0,
+ /** Motion intersected bottom edge of the screen */
+ BOTTOM = 1 << 1,
+ /** Motion intersected left edge of the screen */
+ LEFT = 1 << 2,
+ /** Motion intersected right edge of the screen */
+ RIGHT = 1 << 3,
+};
+
+/** Policy flags */
+enum PolicyFlag : uint32_t {
+ // The following flags originate in RawEvents
+
+ /** Event should wake the device */
+ WAKE = 1 << 0,
+ /** Key is virtual, and should generate haptic feedback */
+ VIRTUAL = 1 << 1,
+ /** Key is the special function modifier */
+ FUNCTION = 1 << 2,
+ /**
+ * Key represents a special gesture that has been detected
+ * by the touch firmware or driver.
+ */
+ GESTURE = 1 << 3,
+
+ // The following flags may be generated here in the InputClassifier HAL
+ // or in later InputListener stages
+
+ /** Event was injected */
+ INJECTED = 1 << 24,
+ /**
+ * Event comes from a trusted source, such as a directly attached input
+ * device or an application with system-wide event injection permission.
+ */
+ TRUSTED = 1 << 25,
+ /** Event has passed through an input filter. */
+ FILTERED = 1 << 26,
+ /** Disable automatic key repeating behaviour. */
+ DISABLE_KEY_REPEAT = 1 << 27,
+
+ // The following flags are set by the input reader policy as it intercepts each event
+
+ /** Device was in an interactive state when the event was intercepted */
+ INTERACTIVE = 1 << 29,
+ /** Event should be dispatched to applications */
+ PASS_TO_USER = 1 << 30,
+};
+
+/**
+ * Buttons that are associated with motion events.
+ */
+enum Button : int32_t {
+ NONE = 0,
+ PRIMARY = 1 << 0,
+ SECONDARY = 1 << 1,
+ TERTIARY = 1 << 2,
+ BACK = 1 << 3,
+ FORWARD = 1 << 4,
+ STYLUS_PRIMARY = 1 << 5,
+ STYLUS_SECONDARY = 1 << 6,
+};
+
+/**
+ * Meta key / modifier state
+ */
+enum Meta : int32_t {
+ NONE = 0,
+
+ /** One of the ALT meta keys is pressed. */
+ ALT_ON = 1 << 1, // 0x02
+
+ /** The left ALT meta key is pressed. */
+ ALT_LEFT_ON = 1 << 4, // 0x10
+
+ /** The right ALT meta key is pressed. */
+ ALT_RIGHT_ON = 1 << 5, // 0x20
+
+ /** One of the SHIFT meta keys is pressed. */
+ SHIFT_ON = 1 << 0, // 0x01
+
+ /** The left SHIFT meta key is pressed. */
+ SHIFT_LEFT_ON = 1 << 6, // 0x40
+
+ /** The right SHIFT meta key is pressed. */
+ SHIFT_RIGHT_ON = 1 << 7, // 0x80
+
+ /** The SYM meta key is pressed. */
+ SYM_ON = 1 << 2, // 0x04
+
+ /** The FUNCTION meta key is pressed. */
+ FUNCTION_ON = 1 << 3, // 0x08
+
+ /** One of the CTRL meta keys is pressed. */
+ CTRL_ON = 1 << 12, // 0x1000
+
+ /** The left CTRL meta key is pressed. */
+ CTRL_LEFT_ON = 1 << 13, // 0x2000
+
+ /** The right CTRL meta key is pressed. */
+ CTRL_RIGHT_ON = 1 << 14, // 0x4000
+
+ /** One of the META meta keys is pressed. */
+ META_ON = 1 << 16, // 0x10000
+
+ /** The left META meta key is pressed. */
+ META_LEFT_ON = 1 << 17, // 0x20000
+
+ /** The right META meta key is pressed. */
+ META_RIGHT_ON = 1 << 18, //0x40000
+
+ /** The CAPS LOCK meta key is on. */
+ CAPS_LOCK_ON = 1 << 20, // 0x100000
+
+ /** The NUM LOCK meta key is on. */
+ NUM_LOCK_ON = 1 << 21, // 0x200000
+
+ /** The SCROLL LOCK meta key is on. */
+ SCROLL_LOCK_ON = 1 << 22, // 0x400000
+};
+
+/**
+ * Motion event flags
+ */
+enum Flag : int32_t {
+ /**
+ * Indicates that the window that received this motion event is partly
+ * or wholly obscured by another visible window above it. This flag is set to true
+ * even if the event did not directly pass through the obscured area.
+ * A security sensitive application can check this flag to identify situations in which
+ * a malicious application may have covered up part of its content for the purpose
+ * of misleading the user or hijacking touches. An appropriate response might be
+ * to drop the suspect touches or to take additional precautions to confirm the user's
+ * actual intent.
+ */
+ WINDOW_IS_OBSCURED = 1 << 0,
+ /**
+ * This flag indicates that the event has been generated by a gesture generator. It
+ * could be used, for example, to determine whether touch slop should be applied.
+ */
+ IS_GENERATED_GESTURE = 1 << 3, // 0x8
+ /**
+ * Motion event is inconsistent with previously sent motion events.
+ */
+ TAINTED = 1 << 31, // 0x80000000
+};
+
+/**
+ * Touch heatmap.
+ *
+ * The array is a 2-D row-major matrix with dimensions (height, width).
+ * The heatmap data does not rotate when device orientation changes.
+ *
+ * Example:
+ *
+ * If the data in the array is:
+ * data[i] = i for i in 0 .. 59,
+ * then it can be represented as follows:
+ *
+ * <-- width -- >
+ * 0 1 2 3 4 5 ^
+ * 6 7 8 9 10 11 |
+ * 12 12 14 15 16 17 |
+ * 18 ... 23 | height
+ * 24 ... 29 |
+ * 30 ... 35 |
+ * 36 ... 41 |
+ * 42 ... 47 |
+ * 48 ... 53 |
+ * 54 ... 59 v
+ *
+ * Looking at the device in standard portrait orientation,
+ * the element "0" is the top left of the screen,
+ * "5" is at the top right, and "59" is the bottom right.
+ * Here width=6, and height=10.
+ */
+struct VideoFrame {
+ /**
+ * Video frame data.
+ * Size of the data is width * height.
+ */
+ vec<int16_t> data;
+ uint32_t width;
+ uint32_t height;
+ /**
+ * Time at which the frame was collected, in nanoseconds.
+ * Measured with the same clock that is used to populate MotionEvent times.
+ */
+ uint64_t timestamp;
+};
+
+/**
+ * Analogous to Android's native MotionEvent / NotifyMotionArgs.
+ * Stores the basic information about pointer movements.
+ */
+struct MotionEvent {
+ // InputEvent fields
+ /**
+ * The id of the device which produced this event.
+ */
+ int32_t deviceId;
+ /**
+ * The source type of this event.
+ */
+ Source source;
+ /**
+ * The display id associated with this event.
+ */
+ int32_t displayId;
+
+ // NotifyMotionArgs fields
+ /**
+ * Time when the initial touch down occurred, in nanoseconds.
+ */
+ int64_t downTime;
+ /**
+ * Time when this event occurred, in nanoseconds.
+ */
+ int64_t eventTime;
+ /**
+ * The kind of action being performed.
+ */
+ Action action;
+ /**
+ * For ACTION_POINTER_DOWN or ACTION_POINTER_UP, this contains the associated pointer index.
+ * The index may be used to get information about the pointer that has gone down or up.
+ */
+ uint8_t actionIndex;
+ /**
+ * The button that has been modified during a press or release action.
+ */
+ Button actionButton;
+ /**
+ * The motion event flags.
+ */
+ bitfield<Flag> flags;
+ /**
+ * The motion event policy flags.
+ */
+ bitfield<PolicyFlag> policyFlags;
+ /**
+ * The edges, if any, that were touched by this motion event.
+ */
+ bitfield<EdgeFlag> edgeFlags;
+ /**
+ * The state of any meta / modifier keys that were in effect when the event was generated.
+ */
+ bitfield<Meta> metaState;
+ /**
+ * The state of buttons that are pressed.
+ */
+ bitfield<Button> buttonState;
+ /**
+ * The precision of the X coordinate being reported.
+ */
+ float xPrecision;
+ /**
+ * The precision of the Y coordinate being reported.
+ */
+ float yPrecision;
+ /**
+ * The properties of each pointer present in this motion event.
+ */
+ vec<PointerProperties> pointerProperties;
+ /**
+ * The coordinates of each pointer.
+ */
+ vec<PointerCoords> pointerCoords;
+
+ // Additional fields from NotifyMotionArgs
+ /**
+ * Device time at which the event occurred, in microseconds.
+ * Will wrap after a little over an hour.
+ */
+ uint32_t deviceTimestamp;
+ /**
+ * The video frames, if any, associated with the current or previous motion events.
+ */
+ vec<VideoFrame> frames;
+};
+
+
+enum Classification : uint8_t {
+ NONE = 0,
+ /**
+ * Too early to classify the gesture, need more events.
+ */
+ AMBIGUOUS_GESTURE = 1,
+ /**
+ * User is force-pressing the screen.
+ */
+ DEEP_PRESS = 2,
+};