blob: d27b80497946c991dd960e0c5f6aa95d044fc8a7 [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
Siarhei Vishniakou98996032022-08-03 11:54:47 -070017#define LOG_TAG "InputProcessor"
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080018
Siarhei Vishniakou98996032022-08-03 11:54:47 -070019#include "InputProcessor.h"
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080020#include "InputCommonConverter.h"
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080021
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080022#include <android-base/stringprintf.h>
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080023#include <android/binder_manager.h>
24#include <android/binder_process.h>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080025#include <inttypes.h>
26#include <log/log.h>
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080027#include <algorithm>
28#include <cmath>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080029#if defined(__linux__)
Siarhei Vishniakou98996032022-08-03 11:54:47 -070030#include <pthread.h>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080031#endif
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080032#include <unordered_set>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080033
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080034#define INDENT1 " "
35#define INDENT2 " "
36#define INDENT3 " "
37#define INDENT4 " "
38#define INDENT5 " "
39
40using android::base::StringPrintf;
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080041using namespace std::chrono_literals;
42using namespace ::aidl::android::hardware::input;
43using aidl::android::hardware::input::processor::IInputProcessor;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080044
45namespace android {
46
Siarhei Vishniakou98996032022-08-03 11:54:47 -070047// Max number of elements to store in mEvents.
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080048static constexpr size_t MAX_EVENTS = 5;
49
Siarhei Vishniakou98996032022-08-03 11:54:47 -070050template <class K, class V>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080051static V getValueForKey(const std::unordered_map<K, V>& map, K key, V defaultValue) {
52 auto it = map.find(key);
53 if (it == map.end()) {
54 return defaultValue;
55 }
56 return it->second;
57}
58
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080059static MotionClassification getMotionClassification(common::Classification classification) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080060 static_assert(MotionClassification::NONE ==
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080061 static_cast<MotionClassification>(common::Classification::NONE));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080062 static_assert(MotionClassification::AMBIGUOUS_GESTURE ==
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080063 static_cast<MotionClassification>(common::Classification::AMBIGUOUS_GESTURE));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080064 static_assert(MotionClassification::DEEP_PRESS ==
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080065 static_cast<MotionClassification>(common::Classification::DEEP_PRESS));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080066 return static_cast<MotionClassification>(classification);
67}
68
69static bool isTouchEvent(const NotifyMotionArgs& args) {
Siarhei Vishniakoud9489572021-11-12 20:08:38 -080070 return isFromSource(args.source, AINPUT_SOURCE_TOUCHPAD) ||
71 isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080072}
73
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080074static void setCurrentThreadName(const char* name) {
75#if defined(__linux__)
76 // Set the thread name for debugging
77 pthread_setname_np(pthread_self(), name);
78#else
79 (void*)(name); // prevent unused variable warning
80#endif
81}
82
83static std::shared_ptr<IInputProcessor> getService() {
84 const std::string aidl_instance_name = std::string(IInputProcessor::descriptor) + "/default";
85
86 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
87 ALOGI("HAL %s is not declared", aidl_instance_name.c_str());
88 return nullptr;
89 }
90
91 ndk::SpAIBinder binder(AServiceManager_waitForService(aidl_instance_name.c_str()));
92 return IInputProcessor::fromBinder(binder);
93}
94
95// Temporarily releases a held mutex for the lifetime of the instance.
96// Named to match std::scoped_lock
97class scoped_unlock {
98public:
99 explicit scoped_unlock(std::mutex& mutex) : mMutex(mutex) { mMutex.unlock(); }
100 ~scoped_unlock() { mMutex.lock(); }
101
102private:
103 std::mutex& mMutex;
104};
105
106// --- ScopedDeathRecipient ---
107ScopedDeathRecipient::ScopedDeathRecipient(AIBinder_DeathRecipient_onBinderDied onBinderDied,
108 void* cookie)
109 : mCookie(cookie) {
110 mRecipient = AIBinder_DeathRecipient_new(onBinderDied);
111}
112
113void ScopedDeathRecipient::linkToDeath(AIBinder* binder) {
114 binder_status_t linked = AIBinder_linkToDeath(binder, mRecipient, mCookie);
115 if (linked != STATUS_OK) {
116 ALOGE("Could not link death recipient to the HAL death");
117 }
118}
119
120ScopedDeathRecipient::~ScopedDeathRecipient() {
121 AIBinder_DeathRecipient_delete(mRecipient);
122}
123
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800124// --- ClassifierEvent ---
125
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700126ClassifierEvent::ClassifierEvent(const NotifyMotionArgs& args)
127 : type(ClassifierEventType::MOTION), args(args){};
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800128
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700129ClassifierEvent::ClassifierEvent(const NotifyDeviceResetArgs& args)
130 : type(ClassifierEventType::DEVICE_RESET), args(args){};
131
132ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::optional<NotifyArgs> args)
133 : type(type), args(args){};
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800134
135ClassifierEvent& ClassifierEvent::operator=(ClassifierEvent&& other) {
136 type = other.type;
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700137 args = other.args;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800138 return *this;
139}
140
141ClassifierEvent ClassifierEvent::createHalResetEvent() {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700142 return ClassifierEvent(ClassifierEventType::HAL_RESET, std::nullopt);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800143}
144
145ClassifierEvent ClassifierEvent::createExitEvent() {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700146 return ClassifierEvent(ClassifierEventType::EXIT, std::nullopt);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800147}
148
149std::optional<int32_t> ClassifierEvent::getDeviceId() const {
150 switch (type) {
151 case ClassifierEventType::MOTION: {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700152 const NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*args);
153 return motionArgs.deviceId;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800154 }
155 case ClassifierEventType::DEVICE_RESET: {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700156 const NotifyDeviceResetArgs& deviceResetArgs = std::get<NotifyDeviceResetArgs>(*args);
157 return deviceResetArgs.deviceId;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800158 }
159 case ClassifierEventType::HAL_RESET: {
160 return std::nullopt;
161 }
162 case ClassifierEventType::EXIT: {
163 return std::nullopt;
164 }
165 }
166}
167
168// --- MotionClassifier ---
169
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800170MotionClassifier::MotionClassifier(std::shared_ptr<IInputProcessor> service)
171 : mEvents(MAX_EVENTS), mService(std::move(service)) {
Siarhei Vishniakou6dbc3f62019-02-04 14:30:11 -0800172 // Under normal operation, we do not need to reset the HAL here. But in the case where system
173 // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
174 // have received events in the past. That means, that HAL could be in an inconsistent state
175 // once it receives events from the newly created MotionClassifier.
176 mEvents.push(ClassifierEvent::createHalResetEvent());
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700177
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800178 mHalThread = std::thread(&MotionClassifier::processEvents, this);
179#if defined(__linux__)
180 // Set the thread name for debugging
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700181 pthread_setname_np(mHalThread.native_handle(), "InputProcessor");
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800182#endif
183}
184
185std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800186 std::shared_ptr<IInputProcessor> service) {
187 LOG_ALWAYS_FATAL_IF(service == nullptr);
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800188 // Using 'new' to access a non-public constructor
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800189 return std::unique_ptr<MotionClassifier>(new MotionClassifier(std::move(service)));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800190}
191
192MotionClassifier::~MotionClassifier() {
193 requestExit();
194 mHalThread.join();
195}
196
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800197/**
198 * Obtain the classification from the HAL for a given MotionEvent.
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700199 * Should only be called from the InputProcessor thread (mHalThread).
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800200 * Should not be called from the thread that notifyMotion runs on.
201 *
202 * There is no way to provide a timeout for a HAL call. So if the HAL takes too long
203 * to return a classification, this would directly impact the touch latency.
204 * To remove any possibility of negatively affecting the touch latency, the HAL
205 * is called from a dedicated thread.
206 */
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800207void MotionClassifier::processEvents() {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800208 while (true) {
209 ClassifierEvent event = mEvents.pop();
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800210 bool halResponseOk = true;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800211 switch (event.type) {
212 case ClassifierEventType::MOTION: {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700213 NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*event.args);
214 common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800215 common::Classification classification;
216 ndk::ScopedAStatus response = mService->classify(motionEvent, &classification);
217 if (response.isOk()) {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700218 updateClassification(motionArgs.deviceId, motionArgs.eventTime,
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800219 getMotionClassification(classification));
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800220 }
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800221 break;
222 }
223 case ClassifierEventType::DEVICE_RESET: {
224 const int32_t deviceId = *(event.getDeviceId());
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800225 halResponseOk = mService->resetDevice(deviceId).isOk();
Siarhei Vishniakoue3021d72020-02-28 15:25:41 -0800226 clearDeviceState(deviceId);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800227 break;
228 }
229 case ClassifierEventType::HAL_RESET: {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800230 halResponseOk = mService->reset().isOk();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800231 clearClassifications();
232 break;
233 }
234 case ClassifierEventType::EXIT: {
235 clearClassifications();
236 return;
237 }
238 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800239 if (!halResponseOk) {
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700240 ALOGE("Error communicating with InputProcessor HAL. "
241 "Exiting MotionClassifier HAL thread");
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800242 clearClassifications();
243 return;
244 }
245 }
246}
247
248void MotionClassifier::enqueueEvent(ClassifierEvent&& event) {
249 bool eventAdded = mEvents.push(std::move(event));
250 if (!eventAdded) {
251 // If the queue is full, suspect the HAL is slow in processing the events.
Siarhei Vishniakou9b5a8212019-07-01 14:25:40 -0700252 ALOGE("Could not add the event to the queue. Resetting");
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800253 reset();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800254 }
255}
256
257void MotionClassifier::requestExit() {
258 reset();
259 mEvents.push(ClassifierEvent::createExitEvent());
260}
261
262void MotionClassifier::updateClassification(int32_t deviceId, nsecs_t eventTime,
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700263 MotionClassification classification) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800264 std::scoped_lock lock(mLock);
265 const nsecs_t lastDownTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
266 if (eventTime < lastDownTime) {
267 // HAL just finished processing an event that belonged to an earlier gesture,
268 // but new gesture is already in progress. Drop this classification.
269 ALOGW("Received late classification. Late by at least %" PRId64 " ms.",
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700270 nanoseconds_to_milliseconds(lastDownTime - eventTime));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800271 return;
272 }
273 mClassifications[deviceId] = classification;
274}
275
276void MotionClassifier::setClassification(int32_t deviceId, MotionClassification classification) {
277 std::scoped_lock lock(mLock);
278 mClassifications[deviceId] = classification;
279}
280
281void MotionClassifier::clearClassifications() {
282 std::scoped_lock lock(mLock);
283 mClassifications.clear();
284}
285
286MotionClassification MotionClassifier::getClassification(int32_t deviceId) {
287 std::scoped_lock lock(mLock);
288 return getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
289}
290
291void MotionClassifier::updateLastDownTime(int32_t deviceId, nsecs_t downTime) {
292 std::scoped_lock lock(mLock);
293 mLastDownTimes[deviceId] = downTime;
294 mClassifications[deviceId] = MotionClassification::NONE;
295}
296
Siarhei Vishniakoue3021d72020-02-28 15:25:41 -0800297void MotionClassifier::clearDeviceState(int32_t deviceId) {
298 std::scoped_lock lock(mLock);
299 mClassifications.erase(deviceId);
300 mLastDownTimes.erase(deviceId);
301}
302
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800303MotionClassification MotionClassifier::classify(const NotifyMotionArgs& args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800304 if ((args.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) {
305 updateLastDownTime(args.deviceId, args.downTime);
306 }
307
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700308 enqueueEvent(args);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800309 return getClassification(args.deviceId);
310}
311
312void MotionClassifier::reset() {
313 mEvents.clear();
314 mEvents.push(ClassifierEvent::createHalResetEvent());
315}
316
317/**
318 * Per-device reset. Clear the outstanding events that are going to be sent to HAL.
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700319 * Request InputProcessor thread to call resetDevice for this particular device.
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800320 */
321void MotionClassifier::reset(const NotifyDeviceResetArgs& args) {
322 int32_t deviceId = args.deviceId;
323 // Clear the pending events right away, to avoid unnecessary work done by the HAL.
324 mEvents.erase([deviceId](const ClassifierEvent& event) {
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700325 std::optional<int32_t> eventDeviceId = event.getDeviceId();
326 return eventDeviceId && (*eventDeviceId == deviceId);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800327 });
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700328 enqueueEvent(args);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800329}
330
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800331void MotionClassifier::dump(std::string& dump) {
332 std::scoped_lock lock(mLock);
Prabir Pradhand7740d62022-07-01 17:54:18 +0000333 dump += StringPrintf(INDENT2 "mService connected: %s\n", mService ? "true" : "false");
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700334 dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n", mEvents.size(), MAX_EVENTS);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800335 dump += INDENT2 "mClassifications, mLastDownTimes:\n";
336 dump += INDENT3 "Device Id\tClassification\tLast down time";
337 // Combine mClassifications and mLastDownTimes into a single table.
338 // Create a superset of device ids.
339 std::unordered_set<int32_t> deviceIds;
340 std::for_each(mClassifications.begin(), mClassifications.end(),
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700341 [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800342 std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700343 [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
344 for (int32_t deviceId : deviceIds) {
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800345 const MotionClassification classification =
346 getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
347 const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700348 dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64, deviceId,
349 motionClassificationToString(classification), downTime);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800350 }
351}
352
Prabir Pradhand7740d62022-07-01 17:54:18 +0000353void MotionClassifier::monitor() {
354 std::scoped_lock lock(mLock);
355 if (mService) {
356 // Ping the HAL service to ensure it is alive and not blocked.
357 const binder_status_t status = AIBinder_ping(mService->asBinder().get());
358 if (status != STATUS_OK) {
359 ALOGW("IInputProcessor HAL is not responding; binder ping result: %s",
360 AStatus_getDescription(AStatus_fromStatus(status)));
361 }
362 }
363}
364
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700365// --- InputProcessor ---
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800366
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700367InputProcessor::InputProcessor(InputListenerInterface& listener) : mQueuedListener(listener) {}
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800368
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700369void InputProcessor::onBinderDied(void* cookie) {
370 InputProcessor* processor = static_cast<InputProcessor*>(cookie);
371 if (processor == nullptr) {
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800372 LOG_ALWAYS_FATAL("Cookie is not valid");
373 return;
374 }
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700375 processor->setMotionClassifierEnabled(false);
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800376}
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700377
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700378void InputProcessor::setMotionClassifierEnabled(bool enabled) {
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800379 std::scoped_lock lock(mLock);
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700380 if (enabled) {
381 ALOGI("Enabling motion classifier");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800382 if (mInitializeMotionClassifier.valid()) {
383 scoped_unlock unlock(mLock);
384 std::future_status status = mInitializeMotionClassifier.wait_for(5s);
385 if (status != std::future_status::ready) {
386 /**
387 * We don't have a better option here than to crash. We can't stop the thread,
388 * and we can't continue because 'mInitializeMotionClassifier' will block in its
389 * destructor.
390 */
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700391 LOG_ALWAYS_FATAL("The thread to load IInputProcessor is stuck!");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800392 }
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700393 }
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800394 mInitializeMotionClassifier = std::async(std::launch::async, [this] {
395 setCurrentThreadName("Create MotionClassifier");
396 std::shared_ptr<IInputProcessor> service = getService();
397 if (service == nullptr) {
398 // Keep the MotionClassifier null, no service was found
399 return;
400 }
401 { // acquire lock
402 std::scoped_lock threadLock(mLock);
403 mHalDeathRecipient =
404 std::make_unique<ScopedDeathRecipient>(onBinderDied, this /*cookie*/);
405 mHalDeathRecipient->linkToDeath(service->asBinder().get());
406 setMotionClassifierLocked(MotionClassifier::create(std::move(service)));
407 } // release lock
408 });
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700409 } else {
410 ALOGI("Disabling motion classifier");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800411 setMotionClassifierLocked(nullptr);
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700412 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800413}
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800414
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700415void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800416 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700417 mQueuedListener.notifyConfigurationChanged(args);
418 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800419}
420
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700421void InputProcessor::notifyKey(const NotifyKeyArgs* args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800422 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700423 mQueuedListener.notifyKey(args);
424 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800425}
426
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700427void InputProcessor::notifyMotion(const NotifyMotionArgs* args) {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700428 { // acquire lock
429 std::scoped_lock lock(mLock);
430 // MotionClassifier is only used for touch events, for now
431 const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
432 if (!sendToMotionClassifier) {
433 mQueuedListener.notifyMotion(args);
434 } else {
435 NotifyMotionArgs newArgs(*args);
436 newArgs.classification = mMotionClassifier->classify(newArgs);
437 mQueuedListener.notifyMotion(&newArgs);
438 }
439 } // release lock
440 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800441}
442
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700443void InputProcessor::notifySensor(const NotifySensorArgs* args) {
Chris Yef59a2f42020-10-16 12:55:26 -0700444 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700445 mQueuedListener.notifySensor(args);
446 mQueuedListener.flush();
Chris Yef59a2f42020-10-16 12:55:26 -0700447}
448
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700449void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs* args) {
Chris Yefb552902021-02-03 17:18:37 -0800450 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700451 mQueuedListener.notifyVibratorState(args);
452 mQueuedListener.flush();
Chris Yefb552902021-02-03 17:18:37 -0800453}
454
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700455void InputProcessor::notifySwitch(const NotifySwitchArgs* args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800456 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700457 mQueuedListener.notifySwitch(args);
458 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800459}
460
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700461void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700462 { // acquire lock
463 std::scoped_lock lock(mLock);
464 if (mMotionClassifier) {
465 mMotionClassifier->reset(*args);
466 }
467 } // release lock
468
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800469 // continue to next stage
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700470 mQueuedListener.notifyDeviceReset(args);
471 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800472}
473
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700474void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
Prabir Pradhan7e186182020-11-10 13:56:45 -0800475 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700476 mQueuedListener.notifyPointerCaptureChanged(args);
477 mQueuedListener.flush();
Prabir Pradhan7e186182020-11-10 13:56:45 -0800478}
479
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700480void InputProcessor::setMotionClassifierLocked(
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800481 std::unique_ptr<MotionClassifierInterface> motionClassifier) REQUIRES(mLock) {
482 if (motionClassifier == nullptr) {
483 // Destroy the ScopedDeathRecipient object, which will cause it to unlinkToDeath.
484 // We can't call 'unlink' here because we don't have the binder handle.
485 mHalDeathRecipient = nullptr;
486 }
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800487 mMotionClassifier = std::move(motionClassifier);
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800488}
489
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700490void InputProcessor::dump(std::string& dump) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800491 std::scoped_lock lock(mLock);
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700492 dump += "Input Processor State:\n";
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800493 dump += INDENT1 "Motion Classifier:\n";
494 if (mMotionClassifier) {
495 mMotionClassifier->dump(dump);
496 } else {
497 dump += INDENT2 "<nullptr>";
498 }
499 dump += "\n";
500}
501
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700502void InputProcessor::monitor() {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700503 std::scoped_lock lock(mLock);
Prabir Pradhand7740d62022-07-01 17:54:18 +0000504 if (mMotionClassifier) mMotionClassifier->monitor();
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700505}
506
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700507InputProcessor::~InputProcessor() {}
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800508
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700509} // namespace android