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