blob: 126cb33b8d4bed2a4ebf223e22a34e0373713853 [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 Vishniakou98996032022-08-03 11:54:47 -0700127ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args)
128 : type(ClassifierEventType::MOTION), args(std::move(args)){};
129ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyDeviceResetArgs> args)
130 : type(ClassifierEventType::DEVICE_RESET), args(std::move(args)){};
131ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::unique_ptr<NotifyArgs> args)
132 : type(type), args(std::move(args)){};
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800133
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700134ClassifierEvent::ClassifierEvent(ClassifierEvent&& other)
135 : type(other.type), args(std::move(other.args)){};
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800136
137ClassifierEvent& ClassifierEvent::operator=(ClassifierEvent&& other) {
138 type = other.type;
139 args = std::move(other.args);
140 return *this;
141}
142
143ClassifierEvent ClassifierEvent::createHalResetEvent() {
144 return ClassifierEvent(ClassifierEventType::HAL_RESET, nullptr);
145}
146
147ClassifierEvent ClassifierEvent::createExitEvent() {
148 return ClassifierEvent(ClassifierEventType::EXIT, nullptr);
149}
150
151std::optional<int32_t> ClassifierEvent::getDeviceId() const {
152 switch (type) {
153 case ClassifierEventType::MOTION: {
154 NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(args.get());
155 return motionArgs->deviceId;
156 }
157 case ClassifierEventType::DEVICE_RESET: {
158 NotifyDeviceResetArgs* deviceResetArgs =
159 static_cast<NotifyDeviceResetArgs*>(args.get());
160 return deviceResetArgs->deviceId;
161 }
162 case ClassifierEventType::HAL_RESET: {
163 return std::nullopt;
164 }
165 case ClassifierEventType::EXIT: {
166 return std::nullopt;
167 }
168 }
169}
170
171// --- MotionClassifier ---
172
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800173MotionClassifier::MotionClassifier(std::shared_ptr<IInputProcessor> service)
174 : mEvents(MAX_EVENTS), mService(std::move(service)) {
Siarhei Vishniakou6dbc3f62019-02-04 14:30:11 -0800175 // Under normal operation, we do not need to reset the HAL here. But in the case where system
176 // crashed, but HAL didn't, we may be connecting to an existing HAL process that might already
177 // have received events in the past. That means, that HAL could be in an inconsistent state
178 // once it receives events from the newly created MotionClassifier.
179 mEvents.push(ClassifierEvent::createHalResetEvent());
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700180
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800181 mHalThread = std::thread(&MotionClassifier::processEvents, this);
182#if defined(__linux__)
183 // Set the thread name for debugging
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700184 pthread_setname_np(mHalThread.native_handle(), "InputProcessor");
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800185#endif
186}
187
188std::unique_ptr<MotionClassifierInterface> MotionClassifier::create(
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800189 std::shared_ptr<IInputProcessor> service) {
190 LOG_ALWAYS_FATAL_IF(service == nullptr);
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800191 // Using 'new' to access a non-public constructor
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800192 return std::unique_ptr<MotionClassifier>(new MotionClassifier(std::move(service)));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800193}
194
195MotionClassifier::~MotionClassifier() {
196 requestExit();
197 mHalThread.join();
198}
199
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800200/**
201 * Obtain the classification from the HAL for a given MotionEvent.
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700202 * Should only be called from the InputProcessor thread (mHalThread).
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800203 * Should not be called from the thread that notifyMotion runs on.
204 *
205 * There is no way to provide a timeout for a HAL call. So if the HAL takes too long
206 * to return a classification, this would directly impact the touch latency.
207 * To remove any possibility of negatively affecting the touch latency, the HAL
208 * is called from a dedicated thread.
209 */
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800210void MotionClassifier::processEvents() {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800211 while (true) {
212 ClassifierEvent event = mEvents.pop();
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800213 bool halResponseOk = true;
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800214 switch (event.type) {
215 case ClassifierEventType::MOTION: {
216 NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(event.args.get());
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800217 common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(*motionArgs);
218 common::Classification classification;
219 ndk::ScopedAStatus response = mService->classify(motionEvent, &classification);
220 if (response.isOk()) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800221 updateClassification(motionArgs->deviceId, motionArgs->eventTime,
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800222 getMotionClassification(classification));
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800223 }
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800224 break;
225 }
226 case ClassifierEventType::DEVICE_RESET: {
227 const int32_t deviceId = *(event.getDeviceId());
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800228 halResponseOk = mService->resetDevice(deviceId).isOk();
Siarhei Vishniakoue3021d72020-02-28 15:25:41 -0800229 clearDeviceState(deviceId);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800230 break;
231 }
232 case ClassifierEventType::HAL_RESET: {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800233 halResponseOk = mService->reset().isOk();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800234 clearClassifications();
235 break;
236 }
237 case ClassifierEventType::EXIT: {
238 clearClassifications();
239 return;
240 }
241 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800242 if (!halResponseOk) {
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700243 ALOGE("Error communicating with InputProcessor HAL. "
244 "Exiting MotionClassifier HAL thread");
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800245 clearClassifications();
246 return;
247 }
248 }
249}
250
251void MotionClassifier::enqueueEvent(ClassifierEvent&& event) {
252 bool eventAdded = mEvents.push(std::move(event));
253 if (!eventAdded) {
254 // If the queue is full, suspect the HAL is slow in processing the events.
Siarhei Vishniakou9b5a8212019-07-01 14:25:40 -0700255 ALOGE("Could not add the event to the queue. Resetting");
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800256 reset();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800257 }
258}
259
260void MotionClassifier::requestExit() {
261 reset();
262 mEvents.push(ClassifierEvent::createExitEvent());
263}
264
265void MotionClassifier::updateClassification(int32_t deviceId, nsecs_t eventTime,
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700266 MotionClassification classification) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800267 std::scoped_lock lock(mLock);
268 const nsecs_t lastDownTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
269 if (eventTime < lastDownTime) {
270 // HAL just finished processing an event that belonged to an earlier gesture,
271 // but new gesture is already in progress. Drop this classification.
272 ALOGW("Received late classification. Late by at least %" PRId64 " ms.",
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700273 nanoseconds_to_milliseconds(lastDownTime - eventTime));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800274 return;
275 }
276 mClassifications[deviceId] = classification;
277}
278
279void MotionClassifier::setClassification(int32_t deviceId, MotionClassification classification) {
280 std::scoped_lock lock(mLock);
281 mClassifications[deviceId] = classification;
282}
283
284void MotionClassifier::clearClassifications() {
285 std::scoped_lock lock(mLock);
286 mClassifications.clear();
287}
288
289MotionClassification MotionClassifier::getClassification(int32_t deviceId) {
290 std::scoped_lock lock(mLock);
291 return getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
292}
293
294void MotionClassifier::updateLastDownTime(int32_t deviceId, nsecs_t downTime) {
295 std::scoped_lock lock(mLock);
296 mLastDownTimes[deviceId] = downTime;
297 mClassifications[deviceId] = MotionClassification::NONE;
298}
299
Siarhei Vishniakoue3021d72020-02-28 15:25:41 -0800300void MotionClassifier::clearDeviceState(int32_t deviceId) {
301 std::scoped_lock lock(mLock);
302 mClassifications.erase(deviceId);
303 mLastDownTimes.erase(deviceId);
304}
305
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800306MotionClassification MotionClassifier::classify(const NotifyMotionArgs& args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800307 if ((args.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) {
308 updateLastDownTime(args.deviceId, args.downTime);
309 }
310
311 ClassifierEvent event(std::make_unique<NotifyMotionArgs>(args));
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800312 enqueueEvent(std::move(event));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800313 return getClassification(args.deviceId);
314}
315
316void MotionClassifier::reset() {
317 mEvents.clear();
318 mEvents.push(ClassifierEvent::createHalResetEvent());
319}
320
321/**
322 * Per-device reset. Clear the outstanding events that are going to be sent to HAL.
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700323 * Request InputProcessor thread to call resetDevice for this particular device.
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800324 */
325void MotionClassifier::reset(const NotifyDeviceResetArgs& args) {
326 int32_t deviceId = args.deviceId;
327 // Clear the pending events right away, to avoid unnecessary work done by the HAL.
328 mEvents.erase([deviceId](const ClassifierEvent& event) {
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700329 std::optional<int32_t> eventDeviceId = event.getDeviceId();
330 return eventDeviceId && (*eventDeviceId == deviceId);
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800331 });
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800332 enqueueEvent(std::make_unique<NotifyDeviceResetArgs>(args));
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800333}
334
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800335void MotionClassifier::dump(std::string& dump) {
336 std::scoped_lock lock(mLock);
Prabir Pradhand7740d62022-07-01 17:54:18 +0000337 dump += StringPrintf(INDENT2 "mService connected: %s\n", mService ? "true" : "false");
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700338 dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n", mEvents.size(), MAX_EVENTS);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800339 dump += INDENT2 "mClassifications, mLastDownTimes:\n";
340 dump += INDENT3 "Device Id\tClassification\tLast down time";
341 // Combine mClassifications and mLastDownTimes into a single table.
342 // Create a superset of device ids.
343 std::unordered_set<int32_t> deviceIds;
344 std::for_each(mClassifications.begin(), mClassifications.end(),
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700345 [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800346 std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700347 [&deviceIds](auto pair) { deviceIds.insert(pair.first); });
348 for (int32_t deviceId : deviceIds) {
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800349 const MotionClassification classification =
350 getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
351 const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700352 dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64, deviceId,
353 motionClassificationToString(classification), downTime);
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800354 }
355}
356
Prabir Pradhand7740d62022-07-01 17:54:18 +0000357void MotionClassifier::monitor() {
358 std::scoped_lock lock(mLock);
359 if (mService) {
360 // Ping the HAL service to ensure it is alive and not blocked.
361 const binder_status_t status = AIBinder_ping(mService->asBinder().get());
362 if (status != STATUS_OK) {
363 ALOGW("IInputProcessor HAL is not responding; binder ping result: %s",
364 AStatus_getDescription(AStatus_fromStatus(status)));
365 }
366 }
367}
368
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700369// --- InputProcessor ---
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800370
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700371InputProcessor::InputProcessor(InputListenerInterface& listener) : mQueuedListener(listener) {}
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800372
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700373void InputProcessor::onBinderDied(void* cookie) {
374 InputProcessor* processor = static_cast<InputProcessor*>(cookie);
375 if (processor == nullptr) {
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800376 LOG_ALWAYS_FATAL("Cookie is not valid");
377 return;
378 }
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700379 processor->setMotionClassifierEnabled(false);
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800380}
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700381
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700382void InputProcessor::setMotionClassifierEnabled(bool enabled) {
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800383 std::scoped_lock lock(mLock);
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700384 if (enabled) {
385 ALOGI("Enabling motion classifier");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800386 if (mInitializeMotionClassifier.valid()) {
387 scoped_unlock unlock(mLock);
388 std::future_status status = mInitializeMotionClassifier.wait_for(5s);
389 if (status != std::future_status::ready) {
390 /**
391 * We don't have a better option here than to crash. We can't stop the thread,
392 * and we can't continue because 'mInitializeMotionClassifier' will block in its
393 * destructor.
394 */
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700395 LOG_ALWAYS_FATAL("The thread to load IInputProcessor is stuck!");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800396 }
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700397 }
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800398 mInitializeMotionClassifier = std::async(std::launch::async, [this] {
399 setCurrentThreadName("Create MotionClassifier");
400 std::shared_ptr<IInputProcessor> service = getService();
401 if (service == nullptr) {
402 // Keep the MotionClassifier null, no service was found
403 return;
404 }
405 { // acquire lock
406 std::scoped_lock threadLock(mLock);
407 mHalDeathRecipient =
408 std::make_unique<ScopedDeathRecipient>(onBinderDied, this /*cookie*/);
409 mHalDeathRecipient->linkToDeath(service->asBinder().get());
410 setMotionClassifierLocked(MotionClassifier::create(std::move(service)));
411 } // release lock
412 });
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700413 } else {
414 ALOGI("Disabling motion classifier");
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800415 setMotionClassifierLocked(nullptr);
Siarhei Vishniakouc9ac19e2020-03-19 11:55:01 -0700416 }
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800417}
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800418
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700419void InputProcessor::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800420 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700421 mQueuedListener.notifyConfigurationChanged(args);
422 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800423}
424
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700425void InputProcessor::notifyKey(const NotifyKeyArgs* args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800426 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700427 mQueuedListener.notifyKey(args);
428 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800429}
430
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700431void InputProcessor::notifyMotion(const NotifyMotionArgs* args) {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700432 { // acquire lock
433 std::scoped_lock lock(mLock);
434 // MotionClassifier is only used for touch events, for now
435 const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
436 if (!sendToMotionClassifier) {
437 mQueuedListener.notifyMotion(args);
438 } else {
439 NotifyMotionArgs newArgs(*args);
Harry Cutts2800fb02022-09-15 13:49:23 +0000440 const MotionClassification newClassification = mMotionClassifier->classify(newArgs);
441 LOG_ALWAYS_FATAL_IF(args->classification != MotionClassification::NONE &&
442 newClassification != MotionClassification::NONE,
443 "Conflicting classifications %s (new) and %s (old)!",
444 motionClassificationToString(newClassification),
445 motionClassificationToString(args->classification));
446 newArgs.classification = newClassification;
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700447 mQueuedListener.notifyMotion(&newArgs);
448 }
449 } // release lock
450 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800451}
452
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700453void InputProcessor::notifySensor(const NotifySensorArgs* args) {
Chris Yef59a2f42020-10-16 12:55:26 -0700454 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700455 mQueuedListener.notifySensor(args);
456 mQueuedListener.flush();
Chris Yef59a2f42020-10-16 12:55:26 -0700457}
458
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700459void InputProcessor::notifyVibratorState(const NotifyVibratorStateArgs* args) {
Chris Yefb552902021-02-03 17:18:37 -0800460 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700461 mQueuedListener.notifyVibratorState(args);
462 mQueuedListener.flush();
Chris Yefb552902021-02-03 17:18:37 -0800463}
464
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700465void InputProcessor::notifySwitch(const NotifySwitchArgs* args) {
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800466 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700467 mQueuedListener.notifySwitch(args);
468 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800469}
470
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700471void InputProcessor::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700472 { // acquire lock
473 std::scoped_lock lock(mLock);
474 if (mMotionClassifier) {
475 mMotionClassifier->reset(*args);
476 }
477 } // release lock
478
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800479 // continue to next stage
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700480 mQueuedListener.notifyDeviceReset(args);
481 mQueuedListener.flush();
Siarhei Vishniakou473174e2017-12-27 16:44:42 -0800482}
483
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700484void InputProcessor::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
Prabir Pradhan7e186182020-11-10 13:56:45 -0800485 // pass through
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700486 mQueuedListener.notifyPointerCaptureChanged(args);
487 mQueuedListener.flush();
Prabir Pradhan7e186182020-11-10 13:56:45 -0800488}
489
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700490void InputProcessor::setMotionClassifierLocked(
Siarhei Vishniakou34d6fef2022-02-01 19:03:45 -0800491 std::unique_ptr<MotionClassifierInterface> motionClassifier) REQUIRES(mLock) {
492 if (motionClassifier == nullptr) {
493 // Destroy the ScopedDeathRecipient object, which will cause it to unlinkToDeath.
494 // We can't call 'unlink' here because we don't have the binder handle.
495 mHalDeathRecipient = nullptr;
496 }
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800497 mMotionClassifier = std::move(motionClassifier);
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800498}
499
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700500void InputProcessor::dump(std::string& dump) {
Siarhei Vishniakou15b66d12019-02-04 14:27:29 -0800501 std::scoped_lock lock(mLock);
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700502 dump += "Input Processor State:\n";
Siarhei Vishniakoua028c442019-02-04 14:33:23 -0800503 dump += INDENT1 "Motion Classifier:\n";
504 if (mMotionClassifier) {
505 mMotionClassifier->dump(dump);
506 } else {
507 dump += INDENT2 "<nullptr>";
508 }
509 dump += "\n";
510}
511
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700512void InputProcessor::monitor() {
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700513 std::scoped_lock lock(mLock);
Prabir Pradhand7740d62022-07-01 17:54:18 +0000514 if (mMotionClassifier) mMotionClassifier->monitor();
Siarhei Vishniakou9f330c52022-05-17 05:03:42 -0700515}
516
Siarhei Vishniakou98996032022-08-03 11:54:47 -0700517InputProcessor::~InputProcessor() {}
Siarhei Vishniakou16523972020-03-04 17:48:39 -0800518
Siarhei Vishniakou4bdbb6a2019-04-11 09:42:09 -0700519} // namespace android