blob: 8b8b1ad4d8d2994dbb28817856756836b8c1eb3e [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>
Harry Cutts2800fb02022-09-15 13:49:23 +000025#include <input/Input.h>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080026#include <inttypes.h>
27#include <log/log.h>
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080028#include <algorithm>
29#include <cmath>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080030#if defined(__linux__)
Siarhei Vishniakou98996032022-08-03 11:54:47 -070031#include <pthread.h>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080032#endif
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080033#include <unordered_set>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080034
Siarhei Vishniakoua028c442019-02-04 14:33:23 -080035#define INDENT1 " "
36#define INDENT2 " "
37#define INDENT3 " "
38#define INDENT4 " "
39#define INDENT5 " "
40
41using android::base::StringPrintf;
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080042using namespace std::chrono_literals;
43using namespace ::aidl::android::hardware::input;
44using aidl::android::hardware::input::processor::IInputProcessor;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080045
46namespace android {
47
Siarhei Vishniakou98996032022-08-03 11:54:47 -070048// Max number of elements to store in mEvents.
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080049static constexpr size_t MAX_EVENTS = 5;
50
Siarhei Vishniakou98996032022-08-03 11:54:47 -070051template <class K, class V>
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080052static 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
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080060static MotionClassification getMotionClassification(common::Classification classification) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080061 static_assert(MotionClassification::NONE ==
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080062 static_cast<MotionClassification>(common::Classification::NONE));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080063 static_assert(MotionClassification::AMBIGUOUS_GESTURE ==
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080064 static_cast<MotionClassification>(common::Classification::AMBIGUOUS_GESTURE));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080065 static_assert(MotionClassification::DEEP_PRESS ==
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080066 static_cast<MotionClassification>(common::Classification::DEEP_PRESS));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080067 return static_cast<MotionClassification>(classification);
68}
69
70static bool isTouchEvent(const NotifyMotionArgs& args) {
Siarhei Vishniakoud9489572021-11-12 20:08:38 -080071 return isFromSource(args.source, AINPUT_SOURCE_TOUCHPAD) ||
72 isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -080073}
74
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -080075static 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
84static 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
98class scoped_unlock {
99public:
100 explicit scoped_unlock(std::mutex& mutex) : mMutex(mutex) { mMutex.unlock(); }
101 ~scoped_unlock() { mMutex.lock(); }
102
103private:
104 std::mutex& mMutex;
105};
106
107// --- ScopedDeathRecipient ---
108ScopedDeathRecipient::ScopedDeathRecipient(AIBinder_DeathRecipient_onBinderDied onBinderDied,
109 void* cookie)
110 : mCookie(cookie) {
111 mRecipient = AIBinder_DeathRecipient_new(onBinderDied);
112}
113
114void 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
121ScopedDeathRecipient::~ScopedDeathRecipient() {
122 AIBinder_DeathRecipient_delete(mRecipient);
123}
124
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800125// --- ClassifierEvent ---
126
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700127ClassifierEvent::ClassifierEvent(const NotifyMotionArgs& args)
128 : type(ClassifierEventType::MOTION), args(args){};
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800129
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700130ClassifierEvent::ClassifierEvent(const NotifyDeviceResetArgs& args)
131 : type(ClassifierEventType::DEVICE_RESET), args(args){};
132
133ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::optional<NotifyArgs> args)
134 : type(type), args(args){};
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800135
136ClassifierEvent& ClassifierEvent::operator=(ClassifierEvent&& other) {
137 type = other.type;
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700138 args = other.args;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800139 return *this;
140}
141
142ClassifierEvent ClassifierEvent::createHalResetEvent() {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700143 return ClassifierEvent(ClassifierEventType::HAL_RESET, std::nullopt);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800144}
145
146ClassifierEvent ClassifierEvent::createExitEvent() {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700147 return ClassifierEvent(ClassifierEventType::EXIT, std::nullopt);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800148}
149
150std::optional<int32_t> ClassifierEvent::getDeviceId() const {
151 switch (type) {
152 case ClassifierEventType::MOTION: {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700153 const NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*args);
154 return motionArgs.deviceId;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800155 }
156 case ClassifierEventType::DEVICE_RESET: {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700157 const NotifyDeviceResetArgs& deviceResetArgs = std::get<NotifyDeviceResetArgs>(*args);
158 return deviceResetArgs.deviceId;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800159 }
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
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800171MotionClassifier::MotionClassifier(std::shared_ptr<IInputProcessor> service)
172 : mEvents(MAX_EVENTS), mService(std::move(service)) {
Siarhei Vishniakou6dbc3f62019-02-04 14:30:11 -0800173 // 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());
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700178
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800179 mHalThread = std::thread(&MotionClassifier::processEvents, this);
180#if defined(__linux__)
181 // Set the thread name for debugging
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700182 pthread_setname_np(mHalThread.native_handle(), "InputProcessor");
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800183#endif
184}
185
186std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800187 std::shared_ptr<IInputProcessor> service) {
188 LOG_ALWAYS_FATAL_IF(service == nullptr);
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800189 // Using 'new' to access a non-public constructor
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800190 return std::unique_ptr<MotionClassifier>(new MotionClassifier(std::move(service)));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800191}
192
193MotionClassifier::~MotionClassifier() {
194 requestExit();
195 mHalThread.join();
196}
197
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800198/**
199 * Obtain the classification from the HAL for a given MotionEvent.
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700200 * Should only be called from the InputProcessor thread (mHalThread).
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800201 * 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 */
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800208void MotionClassifier::processEvents() {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800209 while (true) {
210 ClassifierEvent event = mEvents.pop();
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800211 bool halResponseOk = true;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800212 switch (event.type) {
213 case ClassifierEventType::MOTION: {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700214 NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*event.args);
215 common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800216 common::Classification classification;
217 ndk::ScopedAStatus response = mService->classify(motionEvent, &classification);
218 if (response.isOk()) {
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700219 updateClassification(motionArgs.deviceId, motionArgs.eventTime,
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800220 getMotionClassification(classification));
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800221 }
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800222 break;
223 }
224 case ClassifierEventType::DEVICE_RESET: {
225 const int32_t deviceId = *(event.getDeviceId());
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800226 halResponseOk = mService->resetDevice(deviceId).isOk();
Siarhei Vishniakoue3021d72020-02-28 15:25:41 -0800227 clearDeviceState(deviceId);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800228 break;
229 }
230 case ClassifierEventType::HAL_RESET: {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800231 halResponseOk = mService->reset().isOk();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800232 clearClassifications();
233 break;
234 }
235 case ClassifierEventType::EXIT: {
236 clearClassifications();
237 return;
238 }
239 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800240 if (!halResponseOk) {
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700241 ALOGE("Error communicating with InputProcessor HAL. "
242 "Exiting MotionClassifier HAL thread");
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800243 clearClassifications();
244 return;
245 }
246 }
247}
248
249void 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.
Siarhei Vishniakou9b5a8212019-07-01 14:25:40 -0700253 ALOGE("Could not add the event to the queue. Resetting");
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800254 reset();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800255 }
256}
257
258void MotionClassifier::requestExit() {
259 reset();
260 mEvents.push(ClassifierEvent::createExitEvent());
261}
262
263void MotionClassifier::updateClassification(int32_t deviceId, nsecs_t eventTime,
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700264 MotionClassification classification) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800265 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.",
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700271 nanoseconds_to_milliseconds(lastDownTime - eventTime));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800272 return;
273 }
274 mClassifications[deviceId] = classification;
275}
276
277void MotionClassifier::setClassification(int32_t deviceId, MotionClassification classification) {
278 std::scoped_lock lock(mLock);
279 mClassifications[deviceId] = classification;
280}
281
282void MotionClassifier::clearClassifications() {
283 std::scoped_lock lock(mLock);
284 mClassifications.clear();
285}
286
287MotionClassification MotionClassifier::getClassification(int32_t deviceId) {
288 std::scoped_lock lock(mLock);
289 return getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
290}
291
292void 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
Siarhei Vishniakoue3021d72020-02-28 15:25:41 -0800298void MotionClassifier::clearDeviceState(int32_t deviceId) {
299 std::scoped_lock lock(mLock);
300 mClassifications.erase(deviceId);
301 mLastDownTimes.erase(deviceId);
302}
303
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800304MotionClassification MotionClassifier::classify(const NotifyMotionArgs& args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800305 if ((args.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) {
306 updateLastDownTime(args.deviceId, args.downTime);
307 }
308
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700309 enqueueEvent(args);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800310 return getClassification(args.deviceId);
311}
312
313void 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.
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700320 * Request InputProcessor thread to call resetDevice for this particular device.
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800321 */
322void 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.
Prabir Pradhand5678112023-05-18 01:57:10 +0000325 mEvents.erase_if([deviceId](const ClassifierEvent& event) {
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700326 std::optional<int32_t> eventDeviceId = event.getDeviceId();
327 return eventDeviceId && (*eventDeviceId == deviceId);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800328 });
Siarhei Vishniakou096257c2022-09-15 17:02:20 -0700329 enqueueEvent(args);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800330}
331
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800332void MotionClassifier::dump(std::string& dump) {
333 std::scoped_lock lock(mLock);
Prabir Pradhand7740d62022-07-01 17:54:18 +0000334 dump += StringPrintf(INDENT2 "mService connected: %s\n", mService ? "true" : "false");
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700335 dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n", mEvents.size(), MAX_EVENTS);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800336 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(),
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700342 [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800343 std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700344 [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
345 for (int32_t deviceId : deviceIds) {
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800346 const MotionClassification classification =
347 getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
348 const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700349 dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64, deviceId,
350 motionClassificationToString(classification), downTime);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800351 }
352}
353
Prabir Pradhand7740d62022-07-01 17:54:18 +0000354void 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
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700366// --- InputProcessor ---
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800367
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700368InputProcessor::InputProcessor(InputListenerInterface& listener) : mQueuedListener(listener) {}
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800369
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700370void InputProcessor::onBinderDied(void* cookie) {
371 InputProcessor* processor = static_cast<InputProcessor*>(cookie);
372 if (processor == nullptr) {
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800373 LOG_ALWAYS_FATAL("Cookie is not valid");
374 return;
375 }
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700376 processor->setMotionClassifierEnabled(false);
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800377}
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700378
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700379void InputProcessor::setMotionClassifierEnabled(bool enabled) {
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800380 std::scoped_lock lock(mLock);
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700381 if (enabled) {
382 ALOGI("Enabling motion classifier");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800383 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 */
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700392 LOG_ALWAYS_FATAL("The thread to load IInputProcessor is stuck!");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800393 }
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700394 }
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800395 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 =
Harry Cutts33476232023-01-30 19:57:29 +0000405 std::make_unique<ScopedDeathRecipient>(onBinderDied, /*cookie=*/this);
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800406 mHalDeathRecipient->linkToDeath(service->asBinder().get());
407 setMotionClassifierLocked(MotionClassifier::create(std::move(service)));
408 } // release lock
409 });
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700410 } else {
411 ALOGI("Disabling motion classifier");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800412 setMotionClassifierLocked(nullptr);
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700413 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800414}
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800415
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000416void InputProcessor::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
417 // pass through
418 mQueuedListener.notify(args);
419 mQueuedListener.flush();
420}
421
Prabir Pradhan678438e2023-04-13 19:32:51 +0000422void InputProcessor::notifyKey(const NotifyKeyArgs& args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800423 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700424 mQueuedListener.notifyKey(args);
425 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800426}
427
Prabir Pradhan678438e2023-04-13 19:32:51 +0000428void InputProcessor::notifyMotion(const NotifyMotionArgs& args) {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700429 { // acquire lock
430 std::scoped_lock lock(mLock);
431 // MotionClassifier is only used for touch events, for now
Prabir Pradhan678438e2023-04-13 19:32:51 +0000432 const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(args);
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700433 if (!sendToMotionClassifier) {
434 mQueuedListener.notifyMotion(args);
435 } else {
Prabir Pradhan678438e2023-04-13 19:32:51 +0000436 NotifyMotionArgs newArgs(args);
Harry Cutts2800fb02022-09-15 13:49:23 +0000437 const MotionClassification newClassification = mMotionClassifier->classify(newArgs);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000438 LOG_ALWAYS_FATAL_IF(args.classification != MotionClassification::NONE &&
Harry Cutts2800fb02022-09-15 13:49:23 +0000439 newClassification != MotionClassification::NONE,
440 "Conflicting classifications %s (new) and %s (old)!",
441 motionClassificationToString(newClassification),
Prabir Pradhan678438e2023-04-13 19:32:51 +0000442 motionClassificationToString(args.classification));
Harry Cutts2800fb02022-09-15 13:49:23 +0000443 newArgs.classification = newClassification;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000444 mQueuedListener.notifyMotion(newArgs);
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700445 }
446 } // release lock
447 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800448}
449
Prabir Pradhan678438e2023-04-13 19:32:51 +0000450void InputProcessor::notifySensor(const NotifySensorArgs& args) {
Chris Yef59a2f42020-10-16 12:55:26 -0700451 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700452 mQueuedListener.notifySensor(args);
453 mQueuedListener.flush();
Chris Yef59a2f42020-10-16 12:55:26 -0700454}
455
Prabir Pradhan678438e2023-04-13 19:32:51 +0000456void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs& args) {
Chris Yefb552902021-02-03 17:18:37 -0800457 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700458 mQueuedListener.notifyVibratorState(args);
459 mQueuedListener.flush();
Chris Yefb552902021-02-03 17:18:37 -0800460}
461
Prabir Pradhan678438e2023-04-13 19:32:51 +0000462void InputProcessor::notifySwitch(const NotifySwitchArgs& args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800463 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700464 mQueuedListener.notifySwitch(args);
465 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800466}
467
Prabir Pradhan678438e2023-04-13 19:32:51 +0000468void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700469 { // acquire lock
470 std::scoped_lock lock(mLock);
471 if (mMotionClassifier) {
Prabir Pradhan678438e2023-04-13 19:32:51 +0000472 mMotionClassifier->reset(args);
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700473 }
474 } // release lock
475
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800476 // continue to next stage
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700477 mQueuedListener.notifyDeviceReset(args);
478 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800479}
480
Prabir Pradhan678438e2023-04-13 19:32:51 +0000481void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
Prabir Pradhan7e186182020-11-10 13:56:45 -0800482 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700483 mQueuedListener.notifyPointerCaptureChanged(args);
484 mQueuedListener.flush();
Prabir Pradhan7e186182020-11-10 13:56:45 -0800485}
486
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700487void InputProcessor::setMotionClassifierLocked(
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800488 std::unique_ptr<MotionClassifierInterface> motionClassifier) REQUIRES(mLock) {
489 if (motionClassifier == nullptr) {
490 // Destroy the ScopedDeathRecipient object, which will cause it to unlinkToDeath.
491 // We can't call 'unlink' here because we don't have the binder handle.
492 mHalDeathRecipient = nullptr;
493 }
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800494 mMotionClassifier = std::move(motionClassifier);
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800495}
496
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700497void InputProcessor::dump(std::string& dump) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800498 std::scoped_lock lock(mLock);
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700499 dump += "Input Processor State:\n";
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800500 dump += INDENT1 "Motion Classifier:\n";
501 if (mMotionClassifier) {
502 mMotionClassifier->dump(dump);
503 } else {
504 dump += INDENT2 "<nullptr>";
505 }
506 dump += "\n";
507}
508
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700509void InputProcessor::monitor() {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700510 std::scoped_lock lock(mLock);
Prabir Pradhand7740d62022-07-01 17:54:18 +0000511 if (mMotionClassifier) mMotionClassifier->monitor();
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700512}
513
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700514InputProcessor::~InputProcessor() {}
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800515
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700516} // namespace android