xref: /aosp_15_r20/frameworks/native/services/inputflinger/InputProcessor.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "InputProcessor"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include "InputProcessor.h"
20*38e8c45fSAndroid Build Coastguard Worker #include "InputCommonConverter.h"
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_manager.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <android/binder_process.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <input/Input.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <algorithm>
29*38e8c45fSAndroid Build Coastguard Worker #include <cmath>
30*38e8c45fSAndroid Build Coastguard Worker #if defined(__linux__)
31*38e8c45fSAndroid Build Coastguard Worker #include <pthread.h>
32*38e8c45fSAndroid Build Coastguard Worker #endif
33*38e8c45fSAndroid Build Coastguard Worker #include <unordered_set>
34*38e8c45fSAndroid Build Coastguard Worker 
35*38e8c45fSAndroid Build Coastguard Worker #define INDENT1 "  "
36*38e8c45fSAndroid Build Coastguard Worker #define INDENT2 "    "
37*38e8c45fSAndroid Build Coastguard Worker #define INDENT3 "      "
38*38e8c45fSAndroid Build Coastguard Worker #define INDENT4 "        "
39*38e8c45fSAndroid Build Coastguard Worker #define INDENT5 "          "
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
42*38e8c45fSAndroid Build Coastguard Worker using namespace std::chrono_literals;
43*38e8c45fSAndroid Build Coastguard Worker using namespace ::aidl::android::hardware::input;
44*38e8c45fSAndroid Build Coastguard Worker using aidl::android::hardware::input::processor::IInputProcessor;
45*38e8c45fSAndroid Build Coastguard Worker 
46*38e8c45fSAndroid Build Coastguard Worker namespace android {
47*38e8c45fSAndroid Build Coastguard Worker 
48*38e8c45fSAndroid Build Coastguard Worker // Max number of elements to store in mEvents.
49*38e8c45fSAndroid Build Coastguard Worker static constexpr size_t MAX_EVENTS = 5;
50*38e8c45fSAndroid Build Coastguard Worker 
51*38e8c45fSAndroid Build Coastguard Worker template <class K, class V>
getValueForKey(const std::unordered_map<K,V> & map,K key,V defaultValue)52*38e8c45fSAndroid Build Coastguard Worker static V getValueForKey(const std::unordered_map<K, V>& map, K key, V defaultValue) {
53*38e8c45fSAndroid Build Coastguard Worker     auto it = map.find(key);
54*38e8c45fSAndroid Build Coastguard Worker     if (it == map.end()) {
55*38e8c45fSAndroid Build Coastguard Worker         return defaultValue;
56*38e8c45fSAndroid Build Coastguard Worker     }
57*38e8c45fSAndroid Build Coastguard Worker     return it->second;
58*38e8c45fSAndroid Build Coastguard Worker }
59*38e8c45fSAndroid Build Coastguard Worker 
getMotionClassification(common::Classification classification)60*38e8c45fSAndroid Build Coastguard Worker static MotionClassification getMotionClassification(common::Classification classification) {
61*38e8c45fSAndroid Build Coastguard Worker     static_assert(MotionClassification::NONE ==
62*38e8c45fSAndroid Build Coastguard Worker                   static_cast<MotionClassification>(common::Classification::NONE));
63*38e8c45fSAndroid Build Coastguard Worker     static_assert(MotionClassification::AMBIGUOUS_GESTURE ==
64*38e8c45fSAndroid Build Coastguard Worker                   static_cast<MotionClassification>(common::Classification::AMBIGUOUS_GESTURE));
65*38e8c45fSAndroid Build Coastguard Worker     static_assert(MotionClassification::DEEP_PRESS ==
66*38e8c45fSAndroid Build Coastguard Worker                   static_cast<MotionClassification>(common::Classification::DEEP_PRESS));
67*38e8c45fSAndroid Build Coastguard Worker     return static_cast<MotionClassification>(classification);
68*38e8c45fSAndroid Build Coastguard Worker }
69*38e8c45fSAndroid Build Coastguard Worker 
isTouchEvent(const NotifyMotionArgs & args)70*38e8c45fSAndroid Build Coastguard Worker static bool isTouchEvent(const NotifyMotionArgs& args) {
71*38e8c45fSAndroid Build Coastguard Worker     return isFromSource(args.source, AINPUT_SOURCE_TOUCHPAD) ||
72*38e8c45fSAndroid Build Coastguard Worker             isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN);
73*38e8c45fSAndroid Build Coastguard Worker }
74*38e8c45fSAndroid Build Coastguard Worker 
setCurrentThreadName(const char * name)75*38e8c45fSAndroid Build Coastguard Worker static void setCurrentThreadName(const char* name) {
76*38e8c45fSAndroid Build Coastguard Worker #if defined(__linux__)
77*38e8c45fSAndroid Build Coastguard Worker     // Set the thread name for debugging
78*38e8c45fSAndroid Build Coastguard Worker     pthread_setname_np(pthread_self(), name);
79*38e8c45fSAndroid Build Coastguard Worker #else
80*38e8c45fSAndroid Build Coastguard Worker     (void*)(name); // prevent unused variable warning
81*38e8c45fSAndroid Build Coastguard Worker #endif
82*38e8c45fSAndroid Build Coastguard Worker }
83*38e8c45fSAndroid Build Coastguard Worker 
getService()84*38e8c45fSAndroid Build Coastguard Worker static std::shared_ptr<IInputProcessor> getService() {
85*38e8c45fSAndroid Build Coastguard Worker     const std::string aidl_instance_name = std::string(IInputProcessor::descriptor) + "/default";
86*38e8c45fSAndroid Build Coastguard Worker 
87*38e8c45fSAndroid Build Coastguard Worker     if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
88*38e8c45fSAndroid Build Coastguard Worker         ALOGI("HAL %s is not declared", aidl_instance_name.c_str());
89*38e8c45fSAndroid Build Coastguard Worker         return nullptr;
90*38e8c45fSAndroid Build Coastguard Worker     }
91*38e8c45fSAndroid Build Coastguard Worker 
92*38e8c45fSAndroid Build Coastguard Worker     ndk::SpAIBinder binder(AServiceManager_waitForService(aidl_instance_name.c_str()));
93*38e8c45fSAndroid Build Coastguard Worker     return IInputProcessor::fromBinder(binder);
94*38e8c45fSAndroid Build Coastguard Worker }
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker // Temporarily releases a held mutex for the lifetime of the instance.
97*38e8c45fSAndroid Build Coastguard Worker // Named to match std::scoped_lock
98*38e8c45fSAndroid Build Coastguard Worker class scoped_unlock {
99*38e8c45fSAndroid Build Coastguard Worker public:
scoped_unlock(std::mutex & mutex)100*38e8c45fSAndroid Build Coastguard Worker     explicit scoped_unlock(std::mutex& mutex) : mMutex(mutex) { mMutex.unlock(); }
~scoped_unlock()101*38e8c45fSAndroid Build Coastguard Worker     ~scoped_unlock() { mMutex.lock(); }
102*38e8c45fSAndroid Build Coastguard Worker 
103*38e8c45fSAndroid Build Coastguard Worker private:
104*38e8c45fSAndroid Build Coastguard Worker     std::mutex& mMutex;
105*38e8c45fSAndroid Build Coastguard Worker };
106*38e8c45fSAndroid Build Coastguard Worker 
107*38e8c45fSAndroid Build Coastguard Worker // --- ScopedDeathRecipient ---
ScopedDeathRecipient(AIBinder_DeathRecipient_onBinderDied onBinderDied,void * cookie)108*38e8c45fSAndroid Build Coastguard Worker ScopedDeathRecipient::ScopedDeathRecipient(AIBinder_DeathRecipient_onBinderDied onBinderDied,
109*38e8c45fSAndroid Build Coastguard Worker                                            void* cookie)
110*38e8c45fSAndroid Build Coastguard Worker       : mCookie(cookie) {
111*38e8c45fSAndroid Build Coastguard Worker     mRecipient = AIBinder_DeathRecipient_new(onBinderDied);
112*38e8c45fSAndroid Build Coastguard Worker }
113*38e8c45fSAndroid Build Coastguard Worker 
linkToDeath(AIBinder * binder)114*38e8c45fSAndroid Build Coastguard Worker void ScopedDeathRecipient::linkToDeath(AIBinder* binder) {
115*38e8c45fSAndroid Build Coastguard Worker     binder_status_t linked = AIBinder_linkToDeath(binder, mRecipient, mCookie);
116*38e8c45fSAndroid Build Coastguard Worker     if (linked != STATUS_OK) {
117*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Could not link death recipient to the HAL death");
118*38e8c45fSAndroid Build Coastguard Worker     }
119*38e8c45fSAndroid Build Coastguard Worker }
120*38e8c45fSAndroid Build Coastguard Worker 
~ScopedDeathRecipient()121*38e8c45fSAndroid Build Coastguard Worker ScopedDeathRecipient::~ScopedDeathRecipient() {
122*38e8c45fSAndroid Build Coastguard Worker     AIBinder_DeathRecipient_delete(mRecipient);
123*38e8c45fSAndroid Build Coastguard Worker }
124*38e8c45fSAndroid Build Coastguard Worker 
125*38e8c45fSAndroid Build Coastguard Worker // --- ClassifierEvent ---
126*38e8c45fSAndroid Build Coastguard Worker 
ClassifierEvent(const NotifyMotionArgs & args)127*38e8c45fSAndroid Build Coastguard Worker ClassifierEvent::ClassifierEvent(const NotifyMotionArgs& args)
128*38e8c45fSAndroid Build Coastguard Worker       : type(ClassifierEventType::MOTION), args(args){};
129*38e8c45fSAndroid Build Coastguard Worker 
ClassifierEvent(const NotifyDeviceResetArgs & args)130*38e8c45fSAndroid Build Coastguard Worker ClassifierEvent::ClassifierEvent(const NotifyDeviceResetArgs& args)
131*38e8c45fSAndroid Build Coastguard Worker       : type(ClassifierEventType::DEVICE_RESET), args(args){};
132*38e8c45fSAndroid Build Coastguard Worker 
ClassifierEvent(ClassifierEventType type,std::optional<NotifyArgs> args)133*38e8c45fSAndroid Build Coastguard Worker ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::optional<NotifyArgs> args)
134*38e8c45fSAndroid Build Coastguard Worker       : type(type), args(args){};
135*38e8c45fSAndroid Build Coastguard Worker 
operator =(ClassifierEvent && other)136*38e8c45fSAndroid Build Coastguard Worker ClassifierEvent& ClassifierEvent::operator=(ClassifierEvent&& other) {
137*38e8c45fSAndroid Build Coastguard Worker     type = other.type;
138*38e8c45fSAndroid Build Coastguard Worker     args = other.args;
139*38e8c45fSAndroid Build Coastguard Worker     return *this;
140*38e8c45fSAndroid Build Coastguard Worker }
141*38e8c45fSAndroid Build Coastguard Worker 
createHalResetEvent()142*38e8c45fSAndroid Build Coastguard Worker ClassifierEvent ClassifierEvent::createHalResetEvent() {
143*38e8c45fSAndroid Build Coastguard Worker     return ClassifierEvent(ClassifierEventType::HAL_RESET, std::nullopt);
144*38e8c45fSAndroid Build Coastguard Worker }
145*38e8c45fSAndroid Build Coastguard Worker 
createExitEvent()146*38e8c45fSAndroid Build Coastguard Worker ClassifierEvent ClassifierEvent::createExitEvent() {
147*38e8c45fSAndroid Build Coastguard Worker     return ClassifierEvent(ClassifierEventType::EXIT, std::nullopt);
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker 
getDeviceId() const150*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> ClassifierEvent::getDeviceId() const {
151*38e8c45fSAndroid Build Coastguard Worker     switch (type) {
152*38e8c45fSAndroid Build Coastguard Worker         case ClassifierEventType::MOTION: {
153*38e8c45fSAndroid Build Coastguard Worker             const NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*args);
154*38e8c45fSAndroid Build Coastguard Worker             return motionArgs.deviceId;
155*38e8c45fSAndroid Build Coastguard Worker         }
156*38e8c45fSAndroid Build Coastguard Worker         case ClassifierEventType::DEVICE_RESET: {
157*38e8c45fSAndroid Build Coastguard Worker             const NotifyDeviceResetArgs& deviceResetArgs = std::get<NotifyDeviceResetArgs>(*args);
158*38e8c45fSAndroid Build Coastguard Worker             return deviceResetArgs.deviceId;
159*38e8c45fSAndroid Build Coastguard Worker         }
160*38e8c45fSAndroid Build Coastguard Worker         case ClassifierEventType::HAL_RESET: {
161*38e8c45fSAndroid Build Coastguard Worker             return std::nullopt;
162*38e8c45fSAndroid Build Coastguard Worker         }
163*38e8c45fSAndroid Build Coastguard Worker         case ClassifierEventType::EXIT: {
164*38e8c45fSAndroid Build Coastguard Worker             return std::nullopt;
165*38e8c45fSAndroid Build Coastguard Worker         }
166*38e8c45fSAndroid Build Coastguard Worker     }
167*38e8c45fSAndroid Build Coastguard Worker }
168*38e8c45fSAndroid Build Coastguard Worker 
169*38e8c45fSAndroid Build Coastguard Worker // --- MotionClassifier ---
170*38e8c45fSAndroid Build Coastguard Worker 
MotionClassifier(std::shared_ptr<IInputProcessor> service)171*38e8c45fSAndroid Build Coastguard Worker MotionClassifier::MotionClassifier(std::shared_ptr<IInputProcessor> service)
172*38e8c45fSAndroid Build Coastguard Worker       : mEvents(MAX_EVENTS), mService(std::move(service)) {
173*38e8c45fSAndroid Build Coastguard Worker     // Under normal operation, we do not need to reset the HAL here. But in the case where system
174*38e8c45fSAndroid Build Coastguard Worker     // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
175*38e8c45fSAndroid Build Coastguard Worker     // have received events in the past. That means, that HAL could be in an inconsistent state
176*38e8c45fSAndroid Build Coastguard Worker     // once it receives events from the newly created MotionClassifier.
177*38e8c45fSAndroid Build Coastguard Worker     mEvents.push(ClassifierEvent::createHalResetEvent());
178*38e8c45fSAndroid Build Coastguard Worker 
179*38e8c45fSAndroid Build Coastguard Worker     mHalThread = std::thread(&MotionClassifier::processEvents, this);
180*38e8c45fSAndroid Build Coastguard Worker #if defined(__linux__)
181*38e8c45fSAndroid Build Coastguard Worker     // Set the thread name for debugging
182*38e8c45fSAndroid Build Coastguard Worker     pthread_setname_np(mHalThread.native_handle(), "InputProcessor");
183*38e8c45fSAndroid Build Coastguard Worker #endif
184*38e8c45fSAndroid Build Coastguard Worker }
185*38e8c45fSAndroid Build Coastguard Worker 
create(std::shared_ptr<IInputProcessor> service)186*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
187*38e8c45fSAndroid Build Coastguard Worker         std::shared_ptr<IInputProcessor> service) {
188*38e8c45fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(service == nullptr);
189*38e8c45fSAndroid Build Coastguard Worker     // Using 'new' to access a non-public constructor
190*38e8c45fSAndroid Build Coastguard Worker     return std::unique_ptr<MotionClassifier>(new MotionClassifier(std::move(service)));
191*38e8c45fSAndroid Build Coastguard Worker }
192*38e8c45fSAndroid Build Coastguard Worker 
~MotionClassifier()193*38e8c45fSAndroid Build Coastguard Worker MotionClassifier::~MotionClassifier() {
194*38e8c45fSAndroid Build Coastguard Worker     requestExit();
195*38e8c45fSAndroid Build Coastguard Worker     mHalThread.join();
196*38e8c45fSAndroid Build Coastguard Worker }
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker /**
199*38e8c45fSAndroid Build Coastguard Worker  * Obtain the classification from the HAL for a given MotionEvent.
200*38e8c45fSAndroid Build Coastguard Worker  * Should only be called from the InputProcessor thread (mHalThread).
201*38e8c45fSAndroid Build Coastguard Worker  * Should not be called from the thread that notifyMotion runs on.
202*38e8c45fSAndroid Build Coastguard Worker  *
203*38e8c45fSAndroid Build Coastguard Worker  * There is no way to provide a timeout for a HAL call. So if the HAL takes too long
204*38e8c45fSAndroid Build Coastguard Worker  * to return a classification, this would directly impact the touch latency.
205*38e8c45fSAndroid Build Coastguard Worker  * To remove any possibility of negatively affecting the touch latency, the HAL
206*38e8c45fSAndroid Build Coastguard Worker  * is called from a dedicated thread.
207*38e8c45fSAndroid Build Coastguard Worker  */
processEvents()208*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::processEvents() {
209*38e8c45fSAndroid Build Coastguard Worker     while (true) {
210*38e8c45fSAndroid Build Coastguard Worker         ClassifierEvent event = mEvents.pop();
211*38e8c45fSAndroid Build Coastguard Worker         bool halResponseOk = true;
212*38e8c45fSAndroid Build Coastguard Worker         switch (event.type) {
213*38e8c45fSAndroid Build Coastguard Worker             case ClassifierEventType::MOTION: {
214*38e8c45fSAndroid Build Coastguard Worker                 NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*event.args);
215*38e8c45fSAndroid Build Coastguard Worker                 common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
216*38e8c45fSAndroid Build Coastguard Worker                 common::Classification classification;
217*38e8c45fSAndroid Build Coastguard Worker                 ndk::ScopedAStatus response = mService->classify(motionEvent, &classification);
218*38e8c45fSAndroid Build Coastguard Worker                 if (response.isOk()) {
219*38e8c45fSAndroid Build Coastguard Worker                     updateClassification(motionArgs.deviceId, motionArgs.eventTime,
220*38e8c45fSAndroid Build Coastguard Worker                                          getMotionClassification(classification));
221*38e8c45fSAndroid Build Coastguard Worker                 }
222*38e8c45fSAndroid Build Coastguard Worker                 break;
223*38e8c45fSAndroid Build Coastguard Worker             }
224*38e8c45fSAndroid Build Coastguard Worker             case ClassifierEventType::DEVICE_RESET: {
225*38e8c45fSAndroid Build Coastguard Worker                 const int32_t deviceId = *(event.getDeviceId());
226*38e8c45fSAndroid Build Coastguard Worker                 halResponseOk = mService->resetDevice(deviceId).isOk();
227*38e8c45fSAndroid Build Coastguard Worker                 clearDeviceState(deviceId);
228*38e8c45fSAndroid Build Coastguard Worker                 break;
229*38e8c45fSAndroid Build Coastguard Worker             }
230*38e8c45fSAndroid Build Coastguard Worker             case ClassifierEventType::HAL_RESET: {
231*38e8c45fSAndroid Build Coastguard Worker                 halResponseOk = mService->reset().isOk();
232*38e8c45fSAndroid Build Coastguard Worker                 clearClassifications();
233*38e8c45fSAndroid Build Coastguard Worker                 break;
234*38e8c45fSAndroid Build Coastguard Worker             }
235*38e8c45fSAndroid Build Coastguard Worker             case ClassifierEventType::EXIT: {
236*38e8c45fSAndroid Build Coastguard Worker                 clearClassifications();
237*38e8c45fSAndroid Build Coastguard Worker                 return;
238*38e8c45fSAndroid Build Coastguard Worker             }
239*38e8c45fSAndroid Build Coastguard Worker         }
240*38e8c45fSAndroid Build Coastguard Worker         if (!halResponseOk) {
241*38e8c45fSAndroid Build Coastguard Worker             ALOGE("Error communicating with InputProcessor HAL. "
242*38e8c45fSAndroid Build Coastguard Worker                   "Exiting MotionClassifier HAL thread");
243*38e8c45fSAndroid Build Coastguard Worker             clearClassifications();
244*38e8c45fSAndroid Build Coastguard Worker             return;
245*38e8c45fSAndroid Build Coastguard Worker         }
246*38e8c45fSAndroid Build Coastguard Worker     }
247*38e8c45fSAndroid Build Coastguard Worker }
248*38e8c45fSAndroid Build Coastguard Worker 
enqueueEvent(ClassifierEvent && event)249*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::enqueueEvent(ClassifierEvent&& event) {
250*38e8c45fSAndroid Build Coastguard Worker     bool eventAdded = mEvents.push(std::move(event));
251*38e8c45fSAndroid Build Coastguard Worker     if (!eventAdded) {
252*38e8c45fSAndroid Build Coastguard Worker         // If the queue is full, suspect the HAL is slow in processing the events.
253*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Could not add the event to the queue. Resetting");
254*38e8c45fSAndroid Build Coastguard Worker         reset();
255*38e8c45fSAndroid Build Coastguard Worker     }
256*38e8c45fSAndroid Build Coastguard Worker }
257*38e8c45fSAndroid Build Coastguard Worker 
requestExit()258*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::requestExit() {
259*38e8c45fSAndroid Build Coastguard Worker     reset();
260*38e8c45fSAndroid Build Coastguard Worker     mEvents.push(ClassifierEvent::createExitEvent());
261*38e8c45fSAndroid Build Coastguard Worker }
262*38e8c45fSAndroid Build Coastguard Worker 
updateClassification(int32_t deviceId,nsecs_t eventTime,MotionClassification classification)263*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::updateClassification(int32_t deviceId, nsecs_t eventTime,
264*38e8c45fSAndroid Build Coastguard Worker                                             MotionClassification classification) {
265*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
266*38e8c45fSAndroid Build Coastguard Worker     const nsecs_t lastDownTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
267*38e8c45fSAndroid Build Coastguard Worker     if (eventTime < lastDownTime) {
268*38e8c45fSAndroid Build Coastguard Worker         // HAL just finished processing an event that belonged to an earlier gesture,
269*38e8c45fSAndroid Build Coastguard Worker         // but new gesture is already in progress. Drop this classification.
270*38e8c45fSAndroid Build Coastguard Worker         ALOGW("Received late classification. Late by at least %" PRId64 " ms.",
271*38e8c45fSAndroid Build Coastguard Worker               nanoseconds_to_milliseconds(lastDownTime - eventTime));
272*38e8c45fSAndroid Build Coastguard Worker         return;
273*38e8c45fSAndroid Build Coastguard Worker     }
274*38e8c45fSAndroid Build Coastguard Worker     mClassifications[deviceId] = classification;
275*38e8c45fSAndroid Build Coastguard Worker }
276*38e8c45fSAndroid Build Coastguard Worker 
setClassification(int32_t deviceId,MotionClassification classification)277*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::setClassification(int32_t deviceId, MotionClassification classification) {
278*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
279*38e8c45fSAndroid Build Coastguard Worker     mClassifications[deviceId] = classification;
280*38e8c45fSAndroid Build Coastguard Worker }
281*38e8c45fSAndroid Build Coastguard Worker 
clearClassifications()282*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::clearClassifications() {
283*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
284*38e8c45fSAndroid Build Coastguard Worker     mClassifications.clear();
285*38e8c45fSAndroid Build Coastguard Worker }
286*38e8c45fSAndroid Build Coastguard Worker 
getClassification(int32_t deviceId)287*38e8c45fSAndroid Build Coastguard Worker MotionClassification MotionClassifier::getClassification(int32_t deviceId) {
288*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
289*38e8c45fSAndroid Build Coastguard Worker     return getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
290*38e8c45fSAndroid Build Coastguard Worker }
291*38e8c45fSAndroid Build Coastguard Worker 
updateLastDownTime(int32_t deviceId,nsecs_t downTime)292*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::updateLastDownTime(int32_t deviceId, nsecs_t downTime) {
293*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
294*38e8c45fSAndroid Build Coastguard Worker     mLastDownTimes[deviceId] = downTime;
295*38e8c45fSAndroid Build Coastguard Worker     mClassifications[deviceId] = MotionClassification::NONE;
296*38e8c45fSAndroid Build Coastguard Worker }
297*38e8c45fSAndroid Build Coastguard Worker 
clearDeviceState(int32_t deviceId)298*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::clearDeviceState(int32_t deviceId) {
299*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
300*38e8c45fSAndroid Build Coastguard Worker     mClassifications.erase(deviceId);
301*38e8c45fSAndroid Build Coastguard Worker     mLastDownTimes.erase(deviceId);
302*38e8c45fSAndroid Build Coastguard Worker }
303*38e8c45fSAndroid Build Coastguard Worker 
classify(const NotifyMotionArgs & args)304*38e8c45fSAndroid Build Coastguard Worker MotionClassification MotionClassifier::classify(const NotifyMotionArgs& args) {
305*38e8c45fSAndroid Build Coastguard Worker     if ((args.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) {
306*38e8c45fSAndroid Build Coastguard Worker         updateLastDownTime(args.deviceId, args.downTime);
307*38e8c45fSAndroid Build Coastguard Worker     }
308*38e8c45fSAndroid Build Coastguard Worker 
309*38e8c45fSAndroid Build Coastguard Worker     enqueueEvent(args);
310*38e8c45fSAndroid Build Coastguard Worker     return getClassification(args.deviceId);
311*38e8c45fSAndroid Build Coastguard Worker }
312*38e8c45fSAndroid Build Coastguard Worker 
reset()313*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::reset() {
314*38e8c45fSAndroid Build Coastguard Worker     mEvents.clear();
315*38e8c45fSAndroid Build Coastguard Worker     mEvents.push(ClassifierEvent::createHalResetEvent());
316*38e8c45fSAndroid Build Coastguard Worker }
317*38e8c45fSAndroid Build Coastguard Worker 
318*38e8c45fSAndroid Build Coastguard Worker /**
319*38e8c45fSAndroid Build Coastguard Worker  * Per-device reset. Clear the outstanding events that are going to be sent to HAL.
320*38e8c45fSAndroid Build Coastguard Worker  * Request InputProcessor thread to call resetDevice for this particular device.
321*38e8c45fSAndroid Build Coastguard Worker  */
reset(const NotifyDeviceResetArgs & args)322*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::reset(const NotifyDeviceResetArgs& args) {
323*38e8c45fSAndroid Build Coastguard Worker     int32_t deviceId = args.deviceId;
324*38e8c45fSAndroid Build Coastguard Worker     // Clear the pending events right away, to avoid unnecessary work done by the HAL.
325*38e8c45fSAndroid Build Coastguard Worker     mEvents.erase_if([deviceId](const ClassifierEvent& event) {
326*38e8c45fSAndroid Build Coastguard Worker         std::optional<int32_t> eventDeviceId = event.getDeviceId();
327*38e8c45fSAndroid Build Coastguard Worker         return eventDeviceId && (*eventDeviceId == deviceId);
328*38e8c45fSAndroid Build Coastguard Worker     });
329*38e8c45fSAndroid Build Coastguard Worker     enqueueEvent(args);
330*38e8c45fSAndroid Build Coastguard Worker }
331*38e8c45fSAndroid Build Coastguard Worker 
dump(std::string & dump)332*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::dump(std::string& dump) {
333*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
334*38e8c45fSAndroid Build Coastguard Worker     dump += StringPrintf(INDENT2 "mService connected: %s\n", mService ? "true" : "false");
335*38e8c45fSAndroid Build Coastguard Worker     dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n", mEvents.size(), MAX_EVENTS);
336*38e8c45fSAndroid Build Coastguard Worker     dump += INDENT2 "mClassifications, mLastDownTimes:\n";
337*38e8c45fSAndroid Build Coastguard Worker     dump += INDENT3 "Device Id\tClassification\tLast down time";
338*38e8c45fSAndroid Build Coastguard Worker     // Combine mClassifications and mLastDownTimes into a single table.
339*38e8c45fSAndroid Build Coastguard Worker     // Create a superset of device ids.
340*38e8c45fSAndroid Build Coastguard Worker     std::unordered_set<int32_t> deviceIds;
341*38e8c45fSAndroid Build Coastguard Worker     std::for_each(mClassifications.begin(), mClassifications.end(),
342*38e8c45fSAndroid Build Coastguard Worker                   [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
343*38e8c45fSAndroid Build Coastguard Worker     std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
344*38e8c45fSAndroid Build Coastguard Worker                   [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
345*38e8c45fSAndroid Build Coastguard Worker     for (int32_t deviceId : deviceIds) {
346*38e8c45fSAndroid Build Coastguard Worker         const MotionClassification classification =
347*38e8c45fSAndroid Build Coastguard Worker                 getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
348*38e8c45fSAndroid Build Coastguard Worker         const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
349*38e8c45fSAndroid Build Coastguard Worker         dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64, deviceId,
350*38e8c45fSAndroid Build Coastguard Worker                              motionClassificationToString(classification), downTime);
351*38e8c45fSAndroid Build Coastguard Worker     }
352*38e8c45fSAndroid Build Coastguard Worker }
353*38e8c45fSAndroid Build Coastguard Worker 
monitor()354*38e8c45fSAndroid Build Coastguard Worker void MotionClassifier::monitor() {
355*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
356*38e8c45fSAndroid Build Coastguard Worker     if (mService) {
357*38e8c45fSAndroid Build Coastguard Worker         // Ping the HAL service to ensure it is alive and not blocked.
358*38e8c45fSAndroid Build Coastguard Worker         const binder_status_t status = AIBinder_ping(mService->asBinder().get());
359*38e8c45fSAndroid Build Coastguard Worker         if (status != STATUS_OK) {
360*38e8c45fSAndroid Build Coastguard Worker             ALOGW("IInputProcessor HAL is not responding; binder ping result: %s",
361*38e8c45fSAndroid Build Coastguard Worker                   AStatus_getDescription(AStatus_fromStatus(status)));
362*38e8c45fSAndroid Build Coastguard Worker         }
363*38e8c45fSAndroid Build Coastguard Worker     }
364*38e8c45fSAndroid Build Coastguard Worker }
365*38e8c45fSAndroid Build Coastguard Worker 
366*38e8c45fSAndroid Build Coastguard Worker // --- InputProcessor ---
367*38e8c45fSAndroid Build Coastguard Worker 
InputProcessor(InputListenerInterface & listener)368*38e8c45fSAndroid Build Coastguard Worker InputProcessor::InputProcessor(InputListenerInterface& listener) : mQueuedListener(listener) {}
369*38e8c45fSAndroid Build Coastguard Worker 
onBinderDied(void * cookie)370*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::onBinderDied(void* cookie) {
371*38e8c45fSAndroid Build Coastguard Worker     InputProcessor* processor = static_cast<InputProcessor*>(cookie);
372*38e8c45fSAndroid Build Coastguard Worker     if (processor == nullptr) {
373*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL("Cookie is not valid");
374*38e8c45fSAndroid Build Coastguard Worker         return;
375*38e8c45fSAndroid Build Coastguard Worker     }
376*38e8c45fSAndroid Build Coastguard Worker     processor->setMotionClassifierEnabled(false);
377*38e8c45fSAndroid Build Coastguard Worker }
378*38e8c45fSAndroid Build Coastguard Worker 
setMotionClassifierEnabled(bool enabled)379*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::setMotionClassifierEnabled(bool enabled) {
380*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
381*38e8c45fSAndroid Build Coastguard Worker     if (enabled) {
382*38e8c45fSAndroid Build Coastguard Worker         ALOGI("Enabling motion classifier");
383*38e8c45fSAndroid Build Coastguard Worker         if (mInitializeMotionClassifier.valid()) {
384*38e8c45fSAndroid Build Coastguard Worker             scoped_unlock unlock(mLock);
385*38e8c45fSAndroid Build Coastguard Worker             std::future_status status = mInitializeMotionClassifier.wait_for(5s);
386*38e8c45fSAndroid Build Coastguard Worker             if (status != std::future_status::ready) {
387*38e8c45fSAndroid Build Coastguard Worker                 /**
388*38e8c45fSAndroid Build Coastguard Worker                  * We don't have a better option here than to crash. We can't stop the thread,
389*38e8c45fSAndroid Build Coastguard Worker                  * and we can't continue because 'mInitializeMotionClassifier' will block in its
390*38e8c45fSAndroid Build Coastguard Worker                  * destructor.
391*38e8c45fSAndroid Build Coastguard Worker                  */
392*38e8c45fSAndroid Build Coastguard Worker                 LOG_ALWAYS_FATAL("The thread to load IInputProcessor is stuck!");
393*38e8c45fSAndroid Build Coastguard Worker             }
394*38e8c45fSAndroid Build Coastguard Worker         }
395*38e8c45fSAndroid Build Coastguard Worker         mInitializeMotionClassifier = std::async(std::launch::async, [this] {
396*38e8c45fSAndroid Build Coastguard Worker             setCurrentThreadName("Create MotionClassifier");
397*38e8c45fSAndroid Build Coastguard Worker             std::shared_ptr<IInputProcessor> service = getService();
398*38e8c45fSAndroid Build Coastguard Worker             if (service == nullptr) {
399*38e8c45fSAndroid Build Coastguard Worker                 // Keep the MotionClassifier null, no service was found
400*38e8c45fSAndroid Build Coastguard Worker                 return;
401*38e8c45fSAndroid Build Coastguard Worker             }
402*38e8c45fSAndroid Build Coastguard Worker             { // acquire lock
403*38e8c45fSAndroid Build Coastguard Worker                 std::scoped_lock threadLock(mLock);
404*38e8c45fSAndroid Build Coastguard Worker                 mHalDeathRecipient =
405*38e8c45fSAndroid Build Coastguard Worker                         std::make_unique<ScopedDeathRecipient>(onBinderDied, /*cookie=*/this);
406*38e8c45fSAndroid Build Coastguard Worker                 mHalDeathRecipient->linkToDeath(service->asBinder().get());
407*38e8c45fSAndroid Build Coastguard Worker                 setMotionClassifierLocked(MotionClassifier::create(std::move(service)));
408*38e8c45fSAndroid Build Coastguard Worker             } // release lock
409*38e8c45fSAndroid Build Coastguard Worker         });
410*38e8c45fSAndroid Build Coastguard Worker     } else {
411*38e8c45fSAndroid Build Coastguard Worker         ALOGI("Disabling motion classifier");
412*38e8c45fSAndroid Build Coastguard Worker         setMotionClassifierLocked(nullptr);
413*38e8c45fSAndroid Build Coastguard Worker     }
414*38e8c45fSAndroid Build Coastguard Worker }
415*38e8c45fSAndroid Build Coastguard Worker 
notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs & args)416*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
417*38e8c45fSAndroid Build Coastguard Worker     // pass through
418*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notify(args);
419*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
420*38e8c45fSAndroid Build Coastguard Worker }
421*38e8c45fSAndroid Build Coastguard Worker 
notifyKey(const NotifyKeyArgs & args)422*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifyKey(const NotifyKeyArgs& args) {
423*38e8c45fSAndroid Build Coastguard Worker     // pass through
424*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notifyKey(args);
425*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
426*38e8c45fSAndroid Build Coastguard Worker }
427*38e8c45fSAndroid Build Coastguard Worker 
notifyMotion(const NotifyMotionArgs & args)428*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifyMotion(const NotifyMotionArgs& args) {
429*38e8c45fSAndroid Build Coastguard Worker     { // acquire lock
430*38e8c45fSAndroid Build Coastguard Worker         std::scoped_lock lock(mLock);
431*38e8c45fSAndroid Build Coastguard Worker         // MotionClassifier is only used for touch events, for now
432*38e8c45fSAndroid Build Coastguard Worker         const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(args);
433*38e8c45fSAndroid Build Coastguard Worker         if (!sendToMotionClassifier) {
434*38e8c45fSAndroid Build Coastguard Worker             mQueuedListener.notifyMotion(args);
435*38e8c45fSAndroid Build Coastguard Worker         } else {
436*38e8c45fSAndroid Build Coastguard Worker             NotifyMotionArgs newArgs(args);
437*38e8c45fSAndroid Build Coastguard Worker             const MotionClassification newClassification = mMotionClassifier->classify(newArgs);
438*38e8c45fSAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL_IF(args.classification != MotionClassification::NONE &&
439*38e8c45fSAndroid Build Coastguard Worker                                         newClassification != MotionClassification::NONE,
440*38e8c45fSAndroid Build Coastguard Worker                                 "Conflicting classifications %s (new) and %s (old)!",
441*38e8c45fSAndroid Build Coastguard Worker                                 motionClassificationToString(newClassification),
442*38e8c45fSAndroid Build Coastguard Worker                                 motionClassificationToString(args.classification));
443*38e8c45fSAndroid Build Coastguard Worker             newArgs.classification = newClassification;
444*38e8c45fSAndroid Build Coastguard Worker             mQueuedListener.notifyMotion(newArgs);
445*38e8c45fSAndroid Build Coastguard Worker         }
446*38e8c45fSAndroid Build Coastguard Worker     } // release lock
447*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
448*38e8c45fSAndroid Build Coastguard Worker }
449*38e8c45fSAndroid Build Coastguard Worker 
notifySensor(const NotifySensorArgs & args)450*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifySensor(const NotifySensorArgs& args) {
451*38e8c45fSAndroid Build Coastguard Worker     // pass through
452*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notifySensor(args);
453*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
454*38e8c45fSAndroid Build Coastguard Worker }
455*38e8c45fSAndroid Build Coastguard Worker 
notifyVibratorState(const NotifyVibratorStateArgs & args)456*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs& args) {
457*38e8c45fSAndroid Build Coastguard Worker     // pass through
458*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notifyVibratorState(args);
459*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
460*38e8c45fSAndroid Build Coastguard Worker }
461*38e8c45fSAndroid Build Coastguard Worker 
notifySwitch(const NotifySwitchArgs & args)462*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifySwitch(const NotifySwitchArgs& args) {
463*38e8c45fSAndroid Build Coastguard Worker     // pass through
464*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notifySwitch(args);
465*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
466*38e8c45fSAndroid Build Coastguard Worker }
467*38e8c45fSAndroid Build Coastguard Worker 
notifyDeviceReset(const NotifyDeviceResetArgs & args)468*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
469*38e8c45fSAndroid Build Coastguard Worker     { // acquire lock
470*38e8c45fSAndroid Build Coastguard Worker         std::scoped_lock lock(mLock);
471*38e8c45fSAndroid Build Coastguard Worker         if (mMotionClassifier) {
472*38e8c45fSAndroid Build Coastguard Worker             mMotionClassifier->reset(args);
473*38e8c45fSAndroid Build Coastguard Worker         }
474*38e8c45fSAndroid Build Coastguard Worker     } // release lock
475*38e8c45fSAndroid Build Coastguard Worker 
476*38e8c45fSAndroid Build Coastguard Worker     // continue to next stage
477*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notifyDeviceReset(args);
478*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
479*38e8c45fSAndroid Build Coastguard Worker }
480*38e8c45fSAndroid Build Coastguard Worker 
notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs & args)481*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
482*38e8c45fSAndroid Build Coastguard Worker     // pass through
483*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.notifyPointerCaptureChanged(args);
484*38e8c45fSAndroid Build Coastguard Worker     mQueuedListener.flush();
485*38e8c45fSAndroid Build Coastguard Worker }
486*38e8c45fSAndroid Build Coastguard Worker 
setMotionClassifierLocked(std::unique_ptr<MotionClassifierInterface> motionClassifier)487*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::setMotionClassifierLocked(
488*38e8c45fSAndroid Build Coastguard Worker         std::unique_ptr<MotionClassifierInterface> motionClassifier) REQUIRES(mLock) {
489*38e8c45fSAndroid Build Coastguard Worker     if (motionClassifier == nullptr) {
490*38e8c45fSAndroid Build Coastguard Worker         // Destroy the ScopedDeathRecipient object, which will cause it to unlinkToDeath.
491*38e8c45fSAndroid Build Coastguard Worker         // We can't call 'unlink' here because we don't have the binder handle.
492*38e8c45fSAndroid Build Coastguard Worker         mHalDeathRecipient = nullptr;
493*38e8c45fSAndroid Build Coastguard Worker     }
494*38e8c45fSAndroid Build Coastguard Worker     mMotionClassifier = std::move(motionClassifier);
495*38e8c45fSAndroid Build Coastguard Worker }
496*38e8c45fSAndroid Build Coastguard Worker 
dump(std::string & dump)497*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::dump(std::string& dump) {
498*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
499*38e8c45fSAndroid Build Coastguard Worker     dump += "Input Processor State:\n";
500*38e8c45fSAndroid Build Coastguard Worker     dump += INDENT1 "Motion Classifier:\n";
501*38e8c45fSAndroid Build Coastguard Worker     if (mMotionClassifier) {
502*38e8c45fSAndroid Build Coastguard Worker         mMotionClassifier->dump(dump);
503*38e8c45fSAndroid Build Coastguard Worker     } else {
504*38e8c45fSAndroid Build Coastguard Worker         dump += INDENT2 "<nullptr>";
505*38e8c45fSAndroid Build Coastguard Worker     }
506*38e8c45fSAndroid Build Coastguard Worker     dump += "\n";
507*38e8c45fSAndroid Build Coastguard Worker }
508*38e8c45fSAndroid Build Coastguard Worker 
monitor()509*38e8c45fSAndroid Build Coastguard Worker void InputProcessor::monitor() {
510*38e8c45fSAndroid Build Coastguard Worker     std::scoped_lock lock(mLock);
511*38e8c45fSAndroid Build Coastguard Worker     if (mMotionClassifier) mMotionClassifier->monitor();
512*38e8c45fSAndroid Build Coastguard Worker }
513*38e8c45fSAndroid Build Coastguard Worker 
~InputProcessor()514*38e8c45fSAndroid Build Coastguard Worker InputProcessor::~InputProcessor() {}
515*38e8c45fSAndroid Build Coastguard Worker 
516*38e8c45fSAndroid Build Coastguard Worker } // namespace android
517