blob: b97357dfd7bcda9dcf0dac2fab1763c74b4962f1 [file] [log] [blame]
Siarhei Vishniakou473174e2017-12-27 16:44:42 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _UI_INPUT_CLASSIFIER_H
18#define _UI_INPUT_CLASSIFIER_H
19
Siarhei Vishniakou61291d42019-02-11 18:13:20 -080020#include <android-base/thread_annotations.h>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080021#include <utils/RefBase.h>
22#include <unordered_map>
23#include <thread>
24
25#include "BlockingQueue.h"
26#include "InputListener.h"
27#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
28
29namespace android {
30
31enum class ClassifierEventType : uint8_t {
32 MOTION = 0,
33 DEVICE_RESET = 1,
34 HAL_RESET = 2,
35 EXIT = 3,
36};
37
38struct ClassifierEvent {
39 ClassifierEventType type;
40 std::unique_ptr<NotifyArgs> args;
41
42 ClassifierEvent(ClassifierEventType type, std::unique_ptr<NotifyArgs> args);
43 ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args);
44 ClassifierEvent(std::unique_ptr<NotifyDeviceResetArgs> args);
45 ClassifierEvent(ClassifierEvent&& other);
46 ClassifierEvent& operator=(ClassifierEvent&& other);
47
48 // Convenience function to create a HAL_RESET event
49 static ClassifierEvent createHalResetEvent();
50 // Convenience function to create an EXIT event
51 static ClassifierEvent createExitEvent();
52
53 std::optional<int32_t> getDeviceId() const;
54};
55
56// --- Interfaces ---
57
58/**
59 * Interface for adding a MotionClassification to NotifyMotionArgs.
60 *
61 * To implement, override the classify function.
62 */
63class MotionClassifierInterface {
64public:
65 MotionClassifierInterface() { }
66 virtual ~MotionClassifierInterface() { }
67 /**
68 * Based on the motion event described by NotifyMotionArgs,
69 * provide a MotionClassification for the current gesture.
70 */
71 virtual MotionClassification classify(const NotifyMotionArgs& args) = 0;
72 virtual void reset() = 0;
73 virtual void reset(const NotifyDeviceResetArgs& args) = 0;
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080074
75 /**
76 * Dump the state of the motion classifier
77 */
78 virtual void dump(std::string& dump) = 0;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080079};
80
81/**
82 * Base interface for an InputListener stage.
83 * Provides classification to events.
84 */
85class InputClassifierInterface : public virtual RefBase, public InputListenerInterface {
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080086public:
87 /**
88 * Dump the state of the input classifier.
89 * This method may be called on any thread (usually by the input manager).
90 */
91 virtual void dump(std::string& dump) = 0;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080092protected:
93 InputClassifierInterface() { }
94 virtual ~InputClassifierInterface() { }
95};
96
97// --- Implementations ---
98
99/**
100 * Implementation of MotionClassifierInterface that calls the InputClassifier HAL
101 * in order to determine the classification for the current gesture.
102 *
103 * The InputClassifier HAL may keep track of the entire gesture in order to determine
104 * the classification, and may be hardware-specific. It may use the data in
105 * NotifyMotionArgs::videoFrames field to drive the classification decisions.
106 * The HAL is called from a separate thread.
107 */
Greg Kaiser04b3a052019-01-29 07:10:14 -0800108class MotionClassifier final : public MotionClassifierInterface {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800109public:
110 MotionClassifier(sp<android::hardware::input::classifier::V1_0::IInputClassifier> service);
111 ~MotionClassifier();
112 /**
113 * Classifies events asynchronously; that is, it doesn't block events on a classification,
114 * but instead sends them over to the classifier HAL
115 * and after a classification is determined,
116 * it then marks the next event it sees in the stream with it.
117 *
118 * Therefore, it is acceptable to have the classifications be delayed by 1-2 events
119 * in a particular gesture.
120 */
121 virtual MotionClassification classify(const NotifyMotionArgs& args) override;
122 virtual void reset() override;
123 virtual void reset(const NotifyDeviceResetArgs& args) override;
124
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800125 virtual void dump(std::string& dump) override;
126
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800127private:
128 // The events that need to be sent to the HAL.
129 BlockingQueue<ClassifierEvent> mEvents;
130 /**
131 * Thread that will communicate with InputClassifier HAL.
132 * This should be the only thread that communicates with InputClassifier HAL,
133 * because this thread is allowed to block on the HAL calls.
134 */
135 std::thread mHalThread;
136 /**
137 * Print an error message if the caller is not on the InputClassifier thread.
138 * Caller must supply the name of the calling function as __function__
139 */
140 void ensureHalThread(const char* function);
141 /**
142 * Call the InputClassifier HAL
143 */
144 void callInputClassifierHal();
145 /**
146 * Access to the InputClassifier HAL
147 */
148 sp<android::hardware::input::classifier::V1_0::IInputClassifier> mService;
149 std::mutex mLock;
150 /**
151 * Per-device input classifications. Should only be accessed using the
152 * getClassification / setClassification methods.
153 */
154 std::unordered_map<int32_t /*deviceId*/, MotionClassification>
Siarhei Vishniakou61291d42019-02-11 18:13:20 -0800155 mClassifications GUARDED_BY(mLock);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800156 /**
157 * Set the current classification for a given device.
158 */
159 void setClassification(int32_t deviceId, MotionClassification classification);
160 /**
161 * Get the current classification for a given device.
162 */
163 MotionClassification getClassification(int32_t deviceId);
164 void updateClassification(int32_t deviceId, nsecs_t eventTime,
Siarhei Vishniakou61291d42019-02-11 18:13:20 -0800165 MotionClassification classification);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800166 /**
167 * Clear all current classifications
168 */
169 void clearClassifications();
170 /**
171 * Per-device times when the last ACTION_DOWN was received.
172 * Used to reject late classifications that do not belong to the current gesture.
173 *
174 * Accessed indirectly by both InputClassifier thread and the thread that receives notifyMotion.
175 */
Siarhei Vishniakou61291d42019-02-11 18:13:20 -0800176 std::unordered_map<int32_t /*deviceId*/, nsecs_t /*downTime*/> mLastDownTimes GUARDED_BY(mLock);
177
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800178 void updateLastDownTime(int32_t deviceId, nsecs_t downTime);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800179
180 /**
181 * Exit the InputClassifier HAL thread.
182 * Useful for tests to ensure proper cleanup.
183 */
184 void requestExit();
185};
186
187/**
188 * Implementation of the InputClassifierInterface.
189 * Represents a separate stage of input processing. All of the input events go through this stage.
190 * Acts as a passthrough for all input events except for motion events.
191 * The events of motion type are sent to MotionClassifier.
192 */
193class InputClassifier : public InputClassifierInterface {
194public:
195 explicit InputClassifier(const sp<InputListenerInterface>& listener);
Siarhei Vishniakou45bb0882019-02-04 14:25:28 -0800196
197 virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
198 virtual void notifyKey(const NotifyKeyArgs* args) override;
199 virtual void notifyMotion(const NotifyMotionArgs* args) override;
200 virtual void notifySwitch(const NotifySwitchArgs* args) override;
201 virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800202
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800203 virtual void dump(std::string& dump) override;
204
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800205private:
206 std::unique_ptr<MotionClassifierInterface> mMotionClassifier = nullptr;
207 // The next stage to pass input events to
208 sp<InputListenerInterface> mListener;
209};
210
211} // namespace android
Greg Kaiser04b3a052019-01-29 07:10:14 -0800212#endif