1 /*
2 * Copyright (C) 2010 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 #include "Macros.h"
18
19 #include "InputReader.h"
20
21 #include <android-base/stringprintf.h>
22 #include <com_android_input_flags.h>
23 #include <errno.h>
24 #include <input/Keyboard.h>
25 #include <input/VirtualKeyMap.h>
26 #include <inttypes.h>
27 #include <limits.h>
28 #include <log/log.h>
29 #include <math.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <utils/Errors.h>
34 #include <utils/Thread.h>
35
36 #include "InputDevice.h"
37 #include "include/gestures.h"
38
39 using android::base::StringPrintf;
40
41 namespace android {
42
43 namespace {
44
45 /**
46 * Determines if the identifiers passed are a sub-devices. Sub-devices are physical devices
47 * that expose multiple input device paths such a keyboard that also has a touchpad input.
48 * These are separate devices with unique descriptors in EventHub, but InputReader should
49 * create a single InputDevice for them.
50 * Sub-devices are detected by the following criteria:
51 * 1. The vendor, product, bus, version, and unique id match
52 * 2. The location matches. The location is used to distinguish a single device with multiple
53 * inputs versus the same device plugged into multiple ports.
54 */
55
isSubDevice(const InputDeviceIdentifier & identifier1,const InputDeviceIdentifier & identifier2)56 bool isSubDevice(const InputDeviceIdentifier& identifier1,
57 const InputDeviceIdentifier& identifier2) {
58 return (identifier1.vendor == identifier2.vendor &&
59 identifier1.product == identifier2.product && identifier1.bus == identifier2.bus &&
60 identifier1.version == identifier2.version &&
61 identifier1.uniqueId == identifier2.uniqueId &&
62 identifier1.location == identifier2.location);
63 }
64
isStylusPointerGestureStart(const NotifyMotionArgs & motionArgs)65 bool isStylusPointerGestureStart(const NotifyMotionArgs& motionArgs) {
66 const auto actionMasked = MotionEvent::getActionMasked(motionArgs.action);
67 if (actionMasked != AMOTION_EVENT_ACTION_HOVER_ENTER &&
68 actionMasked != AMOTION_EVENT_ACTION_DOWN &&
69 actionMasked != AMOTION_EVENT_ACTION_POINTER_DOWN) {
70 return false;
71 }
72 const auto actionIndex = MotionEvent::getActionIndex(motionArgs.action);
73 return isStylusToolType(motionArgs.pointerProperties[actionIndex].toolType);
74 }
75
isNewGestureStart(const NotifyMotionArgs & motion)76 bool isNewGestureStart(const NotifyMotionArgs& motion) {
77 return motion.action == AMOTION_EVENT_ACTION_DOWN ||
78 motion.action == AMOTION_EVENT_ACTION_HOVER_ENTER;
79 }
80
isNewGestureStart(const NotifyKeyArgs & key)81 bool isNewGestureStart(const NotifyKeyArgs& key) {
82 return key.action == AKEY_EVENT_ACTION_DOWN;
83 }
84
85 // Return the event's device ID if it marks the start of a new gesture.
getDeviceIdOfNewGesture(const NotifyArgs & args)86 std::optional<DeviceId> getDeviceIdOfNewGesture(const NotifyArgs& args) {
87 if (const auto* motion = std::get_if<NotifyMotionArgs>(&args); motion != nullptr) {
88 return isNewGestureStart(*motion) ? std::make_optional(motion->deviceId) : std::nullopt;
89 }
90 if (const auto* key = std::get_if<NotifyKeyArgs>(&args); key != nullptr) {
91 return isNewGestureStart(*key) ? std::make_optional(key->deviceId) : std::nullopt;
92 }
93 return std::nullopt;
94 }
95
96 } // namespace
97
98 // --- InputReader ---
99
InputReader(std::shared_ptr<EventHubInterface> eventHub,const sp<InputReaderPolicyInterface> & policy,InputListenerInterface & listener)100 InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
101 const sp<InputReaderPolicyInterface>& policy,
102 InputListenerInterface& listener)
103 : mContext(this),
104 mEventHub(eventHub),
105 mPolicy(policy),
106 mNextListener(listener),
107 mKeyboardClassifier(std::make_unique<KeyboardClassifier>()),
108 mGlobalMetaState(AMETA_NONE),
109 mLedMetaState(AMETA_NONE),
110 mGeneration(1),
111 mNextInputDeviceId(END_RESERVED_ID),
112 mDisableVirtualKeysTimeout(LLONG_MIN),
113 mNextTimeout(LLONG_MAX),
114 mConfigurationChangesToRefresh(0) {
115 refreshConfigurationLocked(/*changes=*/{});
116 updateGlobalMetaStateLocked();
117 }
118
~InputReader()119 InputReader::~InputReader() {}
120
start()121 status_t InputReader::start() {
122 if (mThread) {
123 return ALREADY_EXISTS;
124 }
125 mThread = std::make_unique<InputThread>(
126 "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); },
127 /*isInCriticalPath=*/true);
128 return OK;
129 }
130
stop()131 status_t InputReader::stop() {
132 if (mThread && mThread->isCallingThread()) {
133 ALOGE("InputReader cannot be stopped from its own thread!");
134 return INVALID_OPERATION;
135 }
136 mThread.reset();
137 return OK;
138 }
139
loopOnce()140 void InputReader::loopOnce() {
141 int32_t oldGeneration;
142 int32_t timeoutMillis;
143 // Copy some state so that we can access it outside the lock later.
144 bool inputDevicesChanged = false;
145 std::vector<InputDeviceInfo> inputDevices;
146 std::list<NotifyArgs> notifyArgs;
147 { // acquire lock
148 std::scoped_lock _l(mLock);
149
150 oldGeneration = mGeneration;
151 timeoutMillis = -1;
152
153 auto changes = mConfigurationChangesToRefresh;
154 if (changes.any()) {
155 mConfigurationChangesToRefresh.clear();
156 timeoutMillis = 0;
157 refreshConfigurationLocked(changes);
158 } else if (mNextTimeout != LLONG_MAX) {
159 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
160 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
161 }
162 } // release lock
163
164 std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
165
166 { // acquire lock
167 std::scoped_lock _l(mLock);
168 mReaderIsAliveCondition.notify_all();
169
170 if (!events.empty()) {
171 mPendingArgs += processEventsLocked(events.data(), events.size());
172 }
173
174 if (mNextTimeout != LLONG_MAX) {
175 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
176 if (now >= mNextTimeout) {
177 if (debugRawEvents()) {
178 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
179 }
180 mNextTimeout = LLONG_MAX;
181 mPendingArgs += timeoutExpiredLocked(now);
182 }
183 }
184
185 if (oldGeneration != mGeneration) {
186 // Reset global meta state because it depends on connected input devices.
187 updateGlobalMetaStateLocked();
188
189 inputDevicesChanged = true;
190 inputDevices = getInputDevicesLocked();
191 mPendingArgs.emplace_back(
192 NotifyInputDevicesChangedArgs{mContext.getNextId(), inputDevices});
193 }
194
195 std::swap(notifyArgs, mPendingArgs);
196
197 // Keep track of the last used device
198 for (const NotifyArgs& args : notifyArgs) {
199 mLastUsedDeviceId = getDeviceIdOfNewGesture(args).value_or(mLastUsedDeviceId);
200 }
201 } // release lock
202
203 // Flush queued events out to the listener.
204 // This must happen outside of the lock because the listener could potentially call
205 // back into the InputReader's methods, such as getScanCodeState, or become blocked
206 // on another thread similarly waiting to acquire the InputReader lock thereby
207 // resulting in a deadlock. This situation is actually quite plausible because the
208 // listener is actually the input dispatcher, which calls into the window manager,
209 // which occasionally calls into the input reader.
210 for (const NotifyArgs& args : notifyArgs) {
211 mNextListener.notify(args);
212 }
213
214 // Notify the policy that input devices have changed.
215 // This must be done after flushing events down the listener chain to ensure that the rest of
216 // the listeners are synchronized with the changes before the policy reacts to them.
217 if (inputDevicesChanged) {
218 mPolicy->notifyInputDevicesChanged(inputDevices);
219 }
220
221 // Notify the policy of the start of every new stylus gesture.
222 for (const auto& args : notifyArgs) {
223 const auto* motionArgs = std::get_if<NotifyMotionArgs>(&args);
224 if (motionArgs != nullptr && isStylusPointerGestureStart(*motionArgs)) {
225 mPolicy->notifyStylusGestureStarted(motionArgs->deviceId, motionArgs->eventTime);
226 }
227 }
228 }
229
processEventsLocked(const RawEvent * rawEvents,size_t count)230 std::list<NotifyArgs> InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
231 std::list<NotifyArgs> out;
232 for (const RawEvent* rawEvent = rawEvents; count;) {
233 int32_t type = rawEvent->type;
234 size_t batchSize = 1;
235 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
236 int32_t deviceId = rawEvent->deviceId;
237 while (batchSize < count) {
238 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
239 rawEvent[batchSize].deviceId != deviceId) {
240 break;
241 }
242 batchSize += 1;
243 }
244 if (debugRawEvents()) {
245 ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
246 }
247 out += processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
248 } else {
249 switch (rawEvent->type) {
250 case EventHubInterface::DEVICE_ADDED:
251 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
252 break;
253 case EventHubInterface::DEVICE_REMOVED:
254 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
255 break;
256 default:
257 ALOG_ASSERT(false); // can't happen
258 break;
259 }
260 }
261 count -= batchSize;
262 rawEvent += batchSize;
263 }
264 return out;
265 }
266
addDeviceLocked(nsecs_t when,int32_t eventHubId)267 void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
268 if (mDevices.find(eventHubId) != mDevices.end()) {
269 ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
270 return;
271 }
272
273 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
274 std::shared_ptr<InputDevice> device = createDeviceLocked(when, eventHubId, identifier);
275
276 mPendingArgs += device->configure(when, mConfig, /*changes=*/{});
277 mPendingArgs += device->reset(when);
278
279 if (device->isIgnored()) {
280 ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
281 "(ignored non-input device)",
282 device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());
283 } else {
284 ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=%s",
285 device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),
286 inputEventSourceToString(device->getSources()).c_str());
287 }
288
289 mDevices.emplace(eventHubId, device);
290 // Add device to device to EventHub ids map.
291 const auto mapIt = mDeviceToEventHubIdsMap.find(device);
292 if (mapIt == mDeviceToEventHubIdsMap.end()) {
293 std::vector<int32_t> ids = {eventHubId};
294 mDeviceToEventHubIdsMap.emplace(device, ids);
295 } else {
296 mapIt->second.push_back(eventHubId);
297 }
298 bumpGenerationLocked();
299
300 if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {
301 notifyExternalStylusPresenceChangedLocked();
302 }
303
304 // Sensor input device is noisy, to save power disable it by default.
305 // Input device is classified as SENSOR when any sub device is a SENSOR device, check Eventhub
306 // device class to disable SENSOR sub device only.
307 if (mEventHub->getDeviceClasses(eventHubId).test(InputDeviceClass::SENSOR)) {
308 mEventHub->disableDevice(eventHubId);
309 }
310 }
311
removeDeviceLocked(nsecs_t when,int32_t eventHubId)312 void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) {
313 auto deviceIt = mDevices.find(eventHubId);
314 if (deviceIt == mDevices.end()) {
315 ALOGW("Ignoring spurious device removed event for eventHubId %d.", eventHubId);
316 return;
317 }
318
319 std::shared_ptr<InputDevice> device = std::move(deviceIt->second);
320 mDevices.erase(deviceIt);
321 // Erase device from device to EventHub ids map.
322 auto mapIt = mDeviceToEventHubIdsMap.find(device);
323 if (mapIt != mDeviceToEventHubIdsMap.end()) {
324 std::vector<int32_t>& eventHubIds = mapIt->second;
325 std::erase_if(eventHubIds, [eventHubId](int32_t eId) { return eId == eventHubId; });
326 if (eventHubIds.size() == 0) {
327 mDeviceToEventHubIdsMap.erase(mapIt);
328 }
329 }
330 bumpGenerationLocked();
331
332 if (device->isIgnored()) {
333 ALOGI("Device removed: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
334 "(ignored non-input device)",
335 device->getId(), eventHubId, device->getName().c_str(),
336 device->getDescriptor().c_str());
337 } else {
338 ALOGI("Device removed: id=%d, eventHubId=%d, name='%s', descriptor='%s', sources=%s",
339 device->getId(), eventHubId, device->getName().c_str(),
340 device->getDescriptor().c_str(),
341 inputEventSourceToString(device->getSources()).c_str());
342 }
343
344 device->removeEventHubDevice(eventHubId);
345
346 if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {
347 notifyExternalStylusPresenceChangedLocked();
348 }
349
350 if (device->hasEventHubDevices()) {
351 mPendingArgs += device->configure(when, mConfig, /*changes=*/{});
352 }
353 mPendingArgs += device->reset(when);
354 }
355
createDeviceLocked(nsecs_t when,int32_t eventHubId,const InputDeviceIdentifier & identifier)356 std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
357 nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier) {
358 auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
359 const InputDeviceIdentifier identifier2 =
360 devicePair.second->getDeviceInfo().getIdentifier();
361 return isSubDevice(identifier, identifier2);
362 });
363
364 std::shared_ptr<InputDevice> device;
365 if (deviceIt != mDevices.end()) {
366 device = deviceIt->second;
367 } else {
368 int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
369 device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
370 identifier);
371 }
372 mPendingArgs += device->addEventHubDevice(when, eventHubId, mConfig);
373 return device;
374 }
375
processEventsForDeviceLocked(int32_t eventHubId,const RawEvent * rawEvents,size_t count)376 std::list<NotifyArgs> InputReader::processEventsForDeviceLocked(int32_t eventHubId,
377 const RawEvent* rawEvents,
378 size_t count) {
379 auto deviceIt = mDevices.find(eventHubId);
380 if (deviceIt == mDevices.end()) {
381 ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
382 return {};
383 }
384
385 std::shared_ptr<InputDevice>& device = deviceIt->second;
386 if (device->isIgnored()) {
387 // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
388 return {};
389 }
390
391 return device->process(rawEvents, count);
392 }
393
findInputDeviceLocked(int32_t deviceId) const394 InputDevice* InputReader::findInputDeviceLocked(int32_t deviceId) const {
395 auto deviceIt =
396 std::find_if(mDevices.begin(), mDevices.end(), [deviceId](const auto& devicePair) {
397 return devicePair.second->getId() == deviceId;
398 });
399 if (deviceIt != mDevices.end()) {
400 return deviceIt->second.get();
401 }
402 return nullptr;
403 }
404
timeoutExpiredLocked(nsecs_t when)405 std::list<NotifyArgs> InputReader::timeoutExpiredLocked(nsecs_t when) {
406 std::list<NotifyArgs> out;
407 for (auto& devicePair : mDevices) {
408 std::shared_ptr<InputDevice>& device = devicePair.second;
409 if (!device->isIgnored()) {
410 out += device->timeoutExpired(when);
411 }
412 }
413 return out;
414 }
415
nextInputDeviceIdLocked()416 int32_t InputReader::nextInputDeviceIdLocked() {
417 return ++mNextInputDeviceId;
418 }
419
refreshConfigurationLocked(ConfigurationChanges changes)420 void InputReader::refreshConfigurationLocked(ConfigurationChanges changes) {
421 mPolicy->getReaderConfiguration(&mConfig);
422 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
423
424 using Change = InputReaderConfiguration::Change;
425 if (!changes.any()) return;
426
427 ALOGI("Reconfiguring input devices, changes=%s", changes.string().c_str());
428 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
429
430 if (changes.test(Change::MUST_REOPEN)) {
431 mEventHub->requestReopenDevices();
432 } else {
433 for (auto& devicePair : mDevices) {
434 std::shared_ptr<InputDevice>& device = devicePair.second;
435 mPendingArgs += device->configure(now, mConfig, changes);
436 }
437 }
438
439 if (changes.test(Change::POINTER_CAPTURE)) {
440 if (mCurrentPointerCaptureRequest == mConfig.pointerCaptureRequest) {
441 ALOGV("Skipping notifying pointer capture changes: "
442 "There was no change in the pointer capture state.");
443 } else {
444 mCurrentPointerCaptureRequest = mConfig.pointerCaptureRequest;
445 mPendingArgs.emplace_back(
446 NotifyPointerCaptureChangedArgs{mContext.getNextId(), now,
447 mCurrentPointerCaptureRequest});
448 }
449 }
450 }
451
updateGlobalMetaStateLocked()452 void InputReader::updateGlobalMetaStateLocked() {
453 mGlobalMetaState = 0;
454
455 for (auto& devicePair : mDevices) {
456 std::shared_ptr<InputDevice>& device = devicePair.second;
457 mGlobalMetaState |= device->getMetaState();
458 }
459 }
460
getGlobalMetaStateLocked()461 int32_t InputReader::getGlobalMetaStateLocked() {
462 return mGlobalMetaState;
463 }
464
updateLedMetaStateLocked(int32_t metaState)465 void InputReader::updateLedMetaStateLocked(int32_t metaState) {
466 mLedMetaState = metaState;
467 for (auto& devicePair : mDevices) {
468 std::shared_ptr<InputDevice>& device = devicePair.second;
469 device->updateLedState(false);
470 }
471 }
472
getLedMetaStateLocked()473 int32_t InputReader::getLedMetaStateLocked() {
474 return mLedMetaState;
475 }
476
notifyExternalStylusPresenceChangedLocked()477 void InputReader::notifyExternalStylusPresenceChangedLocked() {
478 refreshConfigurationLocked(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
479 }
480
getExternalStylusDevicesLocked(std::vector<InputDeviceInfo> & outDevices)481 void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
482 for (auto& devicePair : mDevices) {
483 std::shared_ptr<InputDevice>& device = devicePair.second;
484 if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS) && !device->isIgnored()) {
485 outDevices.push_back(device->getDeviceInfo());
486 }
487 }
488 }
489
dispatchExternalStylusStateLocked(const StylusState & state)490 std::list<NotifyArgs> InputReader::dispatchExternalStylusStateLocked(const StylusState& state) {
491 std::list<NotifyArgs> out;
492 for (auto& devicePair : mDevices) {
493 std::shared_ptr<InputDevice>& device = devicePair.second;
494 out += device->updateExternalStylusState(state);
495 }
496 return out;
497 }
498
disableVirtualKeysUntilLocked(nsecs_t time)499 void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
500 mDisableVirtualKeysTimeout = time;
501 }
502
shouldDropVirtualKeyLocked(nsecs_t now,int32_t keyCode,int32_t scanCode)503 bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now, int32_t keyCode, int32_t scanCode) {
504 if (now < mDisableVirtualKeysTimeout) {
505 ALOGI("Dropping virtual key from device because virtual keys are "
506 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
507 (mDisableVirtualKeysTimeout - now) * 0.000001, keyCode, scanCode);
508 return true;
509 } else {
510 return false;
511 }
512 }
513
requestTimeoutAtTimeLocked(nsecs_t when)514 void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
515 if (when < mNextTimeout) {
516 mNextTimeout = when;
517 mEventHub->wake();
518 }
519 }
520
bumpGenerationLocked()521 int32_t InputReader::bumpGenerationLocked() {
522 return ++mGeneration;
523 }
524
getInputDevices() const525 std::vector<InputDeviceInfo> InputReader::getInputDevices() const {
526 std::scoped_lock _l(mLock);
527 return getInputDevicesLocked();
528 }
529
getInputDevicesLocked() const530 std::vector<InputDeviceInfo> InputReader::getInputDevicesLocked() const {
531 std::vector<InputDeviceInfo> outInputDevices;
532 outInputDevices.reserve(mDeviceToEventHubIdsMap.size());
533
534 for (const auto& [device, eventHubIds] : mDeviceToEventHubIdsMap) {
535 if (!device->isIgnored()) {
536 outInputDevices.push_back(device->getDeviceInfo());
537 }
538 }
539 return outInputDevices;
540 }
541
getKeyCodeState(int32_t deviceId,uint32_t sourceMask,int32_t keyCode)542 int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) {
543 std::scoped_lock _l(mLock);
544
545 return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
546 }
547
getScanCodeState(int32_t deviceId,uint32_t sourceMask,int32_t scanCode)548 int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) {
549 std::scoped_lock _l(mLock);
550
551 return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
552 }
553
getSwitchState(int32_t deviceId,uint32_t sourceMask,int32_t switchCode)554 int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
555 std::scoped_lock _l(mLock);
556
557 return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
558 }
559
getStateLocked(int32_t deviceId,uint32_t sourceMask,int32_t code,GetStateFunc getStateFunc)560 int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
561 GetStateFunc getStateFunc) {
562 int32_t result = AKEY_STATE_UNKNOWN;
563 if (deviceId >= 0) {
564 InputDevice* device = findInputDeviceLocked(deviceId);
565 if (device && !device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
566 result = (device->*getStateFunc)(sourceMask, code);
567 }
568 } else {
569 for (auto& devicePair : mDevices) {
570 std::shared_ptr<InputDevice>& device = devicePair.second;
571 if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
572 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
573 // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
574 int32_t currentResult = (device.get()->*getStateFunc)(sourceMask, code);
575 if (currentResult >= AKEY_STATE_DOWN) {
576 return currentResult;
577 } else if (currentResult == AKEY_STATE_UP) {
578 result = currentResult;
579 }
580 }
581 }
582 }
583 return result;
584 }
585
toggleCapsLockState(int32_t deviceId)586 void InputReader::toggleCapsLockState(int32_t deviceId) {
587 std::scoped_lock _l(mLock);
588 if (mKeyboardClassifier->getKeyboardType(deviceId) == KeyboardType::ALPHABETIC) {
589 updateLedMetaStateLocked(mLedMetaState ^ AMETA_CAPS_LOCK_ON);
590 }
591 }
592
resetLockedModifierState()593 void InputReader::resetLockedModifierState() {
594 std::scoped_lock _l(mLock);
595 updateLedMetaStateLocked(0);
596 }
597
hasKeys(int32_t deviceId,uint32_t sourceMask,const std::vector<int32_t> & keyCodes,uint8_t * outFlags)598 bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
599 const std::vector<int32_t>& keyCodes, uint8_t* outFlags) {
600 std::scoped_lock _l(mLock);
601
602 memset(outFlags, 0, keyCodes.size());
603 return markSupportedKeyCodesLocked(deviceId, sourceMask, keyCodes, outFlags);
604 }
605
markSupportedKeyCodesLocked(int32_t deviceId,uint32_t sourceMask,const std::vector<int32_t> & keyCodes,uint8_t * outFlags)606 bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
607 const std::vector<int32_t>& keyCodes,
608 uint8_t* outFlags) {
609 bool result = false;
610 if (deviceId >= 0) {
611 InputDevice* device = findInputDeviceLocked(deviceId);
612 if (device && !device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
613 result = device->markSupportedKeyCodes(sourceMask, keyCodes, outFlags);
614 }
615 } else {
616 for (auto& devicePair : mDevices) {
617 std::shared_ptr<InputDevice>& device = devicePair.second;
618 if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
619 result |= device->markSupportedKeyCodes(sourceMask, keyCodes, outFlags);
620 }
621 }
622 }
623 return result;
624 }
625
getKeyCodeForKeyLocation(int32_t deviceId,int32_t locationKeyCode) const626 int32_t InputReader::getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const {
627 std::scoped_lock _l(mLock);
628
629 InputDevice* device = findInputDeviceLocked(deviceId);
630 if (device == nullptr) {
631 ALOGW("Failed to get key code for key location: Input device with id %d not found",
632 deviceId);
633 return AKEYCODE_UNKNOWN;
634 }
635 return device->getKeyCodeForKeyLocation(locationKeyCode);
636 }
637
requestRefreshConfiguration(ConfigurationChanges changes)638 void InputReader::requestRefreshConfiguration(ConfigurationChanges changes) {
639 std::scoped_lock _l(mLock);
640
641 if (changes.any()) {
642 bool needWake = !mConfigurationChangesToRefresh.any();
643 mConfigurationChangesToRefresh |= changes;
644
645 if (needWake) {
646 mEventHub->wake();
647 }
648 }
649 }
650
vibrate(int32_t deviceId,const VibrationSequence & sequence,ssize_t repeat,int32_t token)651 void InputReader::vibrate(int32_t deviceId, const VibrationSequence& sequence, ssize_t repeat,
652 int32_t token) {
653 std::scoped_lock _l(mLock);
654
655 InputDevice* device = findInputDeviceLocked(deviceId);
656 if (device) {
657 mPendingArgs += device->vibrate(sequence, repeat, token);
658 }
659 }
660
cancelVibrate(int32_t deviceId,int32_t token)661 void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
662 std::scoped_lock _l(mLock);
663
664 InputDevice* device = findInputDeviceLocked(deviceId);
665 if (device) {
666 mPendingArgs += device->cancelVibrate(token);
667 }
668 }
669
isVibrating(int32_t deviceId)670 bool InputReader::isVibrating(int32_t deviceId) {
671 std::scoped_lock _l(mLock);
672
673 InputDevice* device = findInputDeviceLocked(deviceId);
674 if (device) {
675 return device->isVibrating();
676 }
677 return false;
678 }
679
getVibratorIds(int32_t deviceId)680 std::vector<int32_t> InputReader::getVibratorIds(int32_t deviceId) {
681 std::scoped_lock _l(mLock);
682
683 InputDevice* device = findInputDeviceLocked(deviceId);
684 if (device) {
685 return device->getVibratorIds();
686 }
687 return {};
688 }
689
disableSensor(int32_t deviceId,InputDeviceSensorType sensorType)690 void InputReader::disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) {
691 std::scoped_lock _l(mLock);
692
693 InputDevice* device = findInputDeviceLocked(deviceId);
694 if (device) {
695 device->disableSensor(sensorType);
696 }
697 }
698
enableSensor(int32_t deviceId,InputDeviceSensorType sensorType,std::chrono::microseconds samplingPeriod,std::chrono::microseconds maxBatchReportLatency)699 bool InputReader::enableSensor(int32_t deviceId, InputDeviceSensorType sensorType,
700 std::chrono::microseconds samplingPeriod,
701 std::chrono::microseconds maxBatchReportLatency) {
702 std::scoped_lock _l(mLock);
703
704 InputDevice* device = findInputDeviceLocked(deviceId);
705 if (device) {
706 return device->enableSensor(sensorType, samplingPeriod, maxBatchReportLatency);
707 }
708 return false;
709 }
710
flushSensor(int32_t deviceId,InputDeviceSensorType sensorType)711 void InputReader::flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) {
712 std::scoped_lock _l(mLock);
713
714 InputDevice* device = findInputDeviceLocked(deviceId);
715 if (device) {
716 device->flushSensor(sensorType);
717 }
718 }
719
getBatteryCapacity(int32_t deviceId)720 std::optional<int32_t> InputReader::getBatteryCapacity(int32_t deviceId) {
721 std::optional<int32_t> eventHubId;
722 {
723 // Do not query the battery state while holding the lock. For some peripheral devices,
724 // reading battery state can be broken and take 5+ seconds. Holding the lock in this case
725 // would block all other event processing during this time. For now, we assume this
726 // call never happens on the InputReader thread and get the battery state outside the
727 // lock to prevent event processing from being blocked by this call.
728 std::scoped_lock _l(mLock);
729 InputDevice* device = findInputDeviceLocked(deviceId);
730 if (!device) return {};
731 eventHubId = device->getBatteryEventHubId();
732 } // release lock
733
734 if (!eventHubId) return {};
735 const auto batteryIds = mEventHub->getRawBatteryIds(*eventHubId);
736 if (batteryIds.empty()) {
737 ALOGW("%s: There are no battery ids for EventHub device %d", __func__, *eventHubId);
738 return {};
739 }
740 return mEventHub->getBatteryCapacity(*eventHubId, batteryIds.front());
741 }
742
getBatteryStatus(int32_t deviceId)743 std::optional<int32_t> InputReader::getBatteryStatus(int32_t deviceId) {
744 std::optional<int32_t> eventHubId;
745 {
746 // Do not query the battery state while holding the lock. For some peripheral devices,
747 // reading battery state can be broken and take 5+ seconds. Holding the lock in this case
748 // would block all other event processing during this time. For now, we assume this
749 // call never happens on the InputReader thread and get the battery state outside the
750 // lock to prevent event processing from being blocked by this call.
751 std::scoped_lock _l(mLock);
752 InputDevice* device = findInputDeviceLocked(deviceId);
753 if (!device) return {};
754 eventHubId = device->getBatteryEventHubId();
755 } // release lock
756
757 if (!eventHubId) return {};
758 const auto batteryIds = mEventHub->getRawBatteryIds(*eventHubId);
759 if (batteryIds.empty()) {
760 ALOGW("%s: There are no battery ids for EventHub device %d", __func__, *eventHubId);
761 return {};
762 }
763 return mEventHub->getBatteryStatus(*eventHubId, batteryIds.front());
764 }
765
getBatteryDevicePath(int32_t deviceId)766 std::optional<std::string> InputReader::getBatteryDevicePath(int32_t deviceId) {
767 std::scoped_lock _l(mLock);
768
769 InputDevice* device = findInputDeviceLocked(deviceId);
770 if (!device) return {};
771
772 std::optional<int32_t> eventHubId = device->getBatteryEventHubId();
773 if (!eventHubId) return {};
774 const auto batteryIds = mEventHub->getRawBatteryIds(*eventHubId);
775 if (batteryIds.empty()) {
776 ALOGW("%s: There are no battery ids for EventHub device %d", __func__, *eventHubId);
777 return {};
778 }
779 const auto batteryInfo = mEventHub->getRawBatteryInfo(*eventHubId, batteryIds.front());
780 if (!batteryInfo) {
781 ALOGW("%s: Failed to get RawBatteryInfo for battery %d of EventHub device %d", __func__,
782 batteryIds.front(), *eventHubId);
783 return {};
784 }
785 return batteryInfo->path;
786 }
787
getLights(int32_t deviceId)788 std::vector<InputDeviceLightInfo> InputReader::getLights(int32_t deviceId) {
789 std::scoped_lock _l(mLock);
790
791 InputDevice* device = findInputDeviceLocked(deviceId);
792 if (device == nullptr) {
793 return {};
794 }
795
796 return device->getDeviceInfo().getLights();
797 }
798
getSensors(int32_t deviceId)799 std::vector<InputDeviceSensorInfo> InputReader::getSensors(int32_t deviceId) {
800 std::scoped_lock _l(mLock);
801
802 InputDevice* device = findInputDeviceLocked(deviceId);
803 if (device == nullptr) {
804 return {};
805 }
806
807 return device->getDeviceInfo().getSensors();
808 }
809
getTouchpadHardwareProperties(int32_t deviceId)810 std::optional<HardwareProperties> InputReader::getTouchpadHardwareProperties(int32_t deviceId) {
811 std::scoped_lock _l(mLock);
812
813 InputDevice* device = findInputDeviceLocked(deviceId);
814
815 if (device == nullptr) {
816 return {};
817 }
818
819 return device->getTouchpadHardwareProperties();
820 }
821
setLightColor(int32_t deviceId,int32_t lightId,int32_t color)822 bool InputReader::setLightColor(int32_t deviceId, int32_t lightId, int32_t color) {
823 std::scoped_lock _l(mLock);
824
825 InputDevice* device = findInputDeviceLocked(deviceId);
826 if (device) {
827 return device->setLightColor(lightId, color);
828 }
829 return false;
830 }
831
setLightPlayerId(int32_t deviceId,int32_t lightId,int32_t playerId)832 bool InputReader::setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) {
833 std::scoped_lock _l(mLock);
834
835 InputDevice* device = findInputDeviceLocked(deviceId);
836 if (device) {
837 return device->setLightPlayerId(lightId, playerId);
838 }
839 return false;
840 }
841
getLightColor(int32_t deviceId,int32_t lightId)842 std::optional<int32_t> InputReader::getLightColor(int32_t deviceId, int32_t lightId) {
843 std::scoped_lock _l(mLock);
844
845 InputDevice* device = findInputDeviceLocked(deviceId);
846 if (device) {
847 return device->getLightColor(lightId);
848 }
849 return std::nullopt;
850 }
851
getLightPlayerId(int32_t deviceId,int32_t lightId)852 std::optional<int32_t> InputReader::getLightPlayerId(int32_t deviceId, int32_t lightId) {
853 std::scoped_lock _l(mLock);
854
855 InputDevice* device = findInputDeviceLocked(deviceId);
856 if (device) {
857 return device->getLightPlayerId(lightId);
858 }
859 return std::nullopt;
860 }
861
getBluetoothAddress(int32_t deviceId) const862 std::optional<std::string> InputReader::getBluetoothAddress(int32_t deviceId) const {
863 std::scoped_lock _l(mLock);
864
865 InputDevice* device = findInputDeviceLocked(deviceId);
866 if (device) {
867 return device->getBluetoothAddress();
868 }
869 return std::nullopt;
870 }
871
canDispatchToDisplay(int32_t deviceId,ui::LogicalDisplayId displayId)872 bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId displayId) {
873 std::scoped_lock _l(mLock);
874
875 InputDevice* device = findInputDeviceLocked(deviceId);
876 if (!device) {
877 ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
878 return false;
879 }
880
881 if (!device->isEnabled()) {
882 ALOGW("Ignoring disabled device %s", device->getName().c_str());
883 return false;
884 }
885
886 std::optional<ui::LogicalDisplayId> associatedDisplayId = device->getAssociatedDisplayId();
887 // No associated display. By default, can dispatch to all displays.
888 if (!associatedDisplayId || !associatedDisplayId->isValid()) {
889 return true;
890 }
891
892 return *associatedDisplayId == displayId;
893 }
894
sysfsNodeChanged(const std::string & sysfsNodePath)895 void InputReader::sysfsNodeChanged(const std::string& sysfsNodePath) {
896 mEventHub->sysfsNodeChanged(sysfsNodePath);
897 }
898
getLastUsedInputDeviceId()899 DeviceId InputReader::getLastUsedInputDeviceId() {
900 std::scoped_lock _l(mLock);
901 return mLastUsedDeviceId;
902 }
903
notifyMouseCursorFadedOnTyping()904 void InputReader::notifyMouseCursorFadedOnTyping() {
905 std::scoped_lock _l(mLock);
906 // disable touchpad taps when cursor has faded due to typing
907 mPreventingTouchpadTaps = true;
908 }
909
setKernelWakeEnabled(int32_t deviceId,bool enabled)910 bool InputReader::setKernelWakeEnabled(int32_t deviceId, bool enabled) {
911 std::scoped_lock _l(mLock);
912 if (!com::android::input::flags::set_input_device_kernel_wake()){
913 return false;
914 }
915 InputDevice* device = findInputDeviceLocked(deviceId);
916 if (device) {
917 return device->setKernelWakeEnabled(enabled);
918 }
919 return false;
920 }
921
dump(std::string & dump)922 void InputReader::dump(std::string& dump) {
923 std::scoped_lock _l(mLock);
924
925 mEventHub->dump(dump);
926 dump += "\n";
927
928 dump += StringPrintf("Input Reader State (Nums of device: %zu):\n",
929 mDeviceToEventHubIdsMap.size());
930
931 for (const auto& devicePair : mDeviceToEventHubIdsMap) {
932 const std::shared_ptr<InputDevice>& device = devicePair.first;
933 std::string eventHubDevStr = INDENT "EventHub Devices: [ ";
934 for (const auto& eId : devicePair.second) {
935 eventHubDevStr += StringPrintf("%d ", eId);
936 }
937 eventHubDevStr += "] \n";
938 device->dump(dump, eventHubDevStr);
939 }
940
941 dump += StringPrintf(INDENT "NextTimeout: %" PRId64 "\n", mNextTimeout);
942 dump += INDENT "Configuration:\n";
943 dump += INDENT2 "ExcludedDeviceNames: [";
944 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
945 if (i != 0) {
946 dump += ", ";
947 }
948 dump += mConfig.excludedDeviceNames[i];
949 }
950 dump += "]\n";
951 dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
952 mConfig.virtualKeyQuietTime * 0.000001f);
953
954 dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
955 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, "
956 "acceleration=%0.3f\n",
957 mConfig.pointerVelocityControlParameters.scale,
958 mConfig.pointerVelocityControlParameters.lowThreshold,
959 mConfig.pointerVelocityControlParameters.highThreshold,
960 mConfig.pointerVelocityControlParameters.acceleration);
961
962 dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
963 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, "
964 "acceleration=%0.3f\n",
965 mConfig.wheelVelocityControlParameters.scale,
966 mConfig.wheelVelocityControlParameters.lowThreshold,
967 mConfig.wheelVelocityControlParameters.highThreshold,
968 mConfig.wheelVelocityControlParameters.acceleration);
969
970 dump += StringPrintf(INDENT2 "PointerGesture:\n");
971 dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(mConfig.pointerGesturesEnabled));
972 dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
973 mConfig.pointerGestureQuietInterval * 0.000001f);
974 dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
975 mConfig.pointerGestureDragMinSwitchSpeed);
976 dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
977 mConfig.pointerGestureTapInterval * 0.000001f);
978 dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
979 mConfig.pointerGestureTapDragInterval * 0.000001f);
980 dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n", mConfig.pointerGestureTapSlop);
981 dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
982 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
983 dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
984 mConfig.pointerGestureMultitouchMinDistance);
985 dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
986 mConfig.pointerGestureSwipeTransitionAngleCosine);
987 dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
988 mConfig.pointerGestureSwipeMaxWidthRatio);
989 dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
990 mConfig.pointerGestureMovementSpeedRatio);
991 dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n", mConfig.pointerGestureZoomSpeedRatio);
992
993 dump += INDENT3 "Viewports:\n";
994 mConfig.dump(dump);
995 }
996
monitor()997 void InputReader::monitor() {
998 // Acquire and release the lock to ensure that the reader has not deadlocked.
999 std::unique_lock<std::mutex> lock(mLock);
1000 mEventHub->wake();
1001 mReaderIsAliveCondition.wait(lock);
1002 // Check the EventHub
1003 mEventHub->monitor();
1004 }
1005
1006 // --- InputReader::ContextImpl ---
1007
ContextImpl(InputReader * reader)1008 InputReader::ContextImpl::ContextImpl(InputReader* reader)
1009 : mReader(reader), mIdGenerator(IdGenerator::Source::INPUT_READER) {}
1010
updateGlobalMetaState()1011 void InputReader::ContextImpl::updateGlobalMetaState() {
1012 // lock is already held by the input loop
1013 mReader->updateGlobalMetaStateLocked();
1014 }
1015
getGlobalMetaState()1016 int32_t InputReader::ContextImpl::getGlobalMetaState() {
1017 // lock is already held by the input loop
1018 return mReader->getGlobalMetaStateLocked();
1019 }
1020
updateLedMetaState(int32_t metaState)1021 void InputReader::ContextImpl::updateLedMetaState(int32_t metaState) {
1022 // lock is already held by the input loop
1023 mReader->updateLedMetaStateLocked(metaState);
1024 }
1025
getLedMetaState()1026 int32_t InputReader::ContextImpl::getLedMetaState() {
1027 // lock is already held by the input loop
1028 return mReader->getLedMetaStateLocked();
1029 }
1030
setPreventingTouchpadTaps(bool prevent)1031 void InputReader::ContextImpl::setPreventingTouchpadTaps(bool prevent) {
1032 // lock is already held by the input loop
1033 mReader->mPreventingTouchpadTaps = prevent;
1034 }
1035
isPreventingTouchpadTaps()1036 bool InputReader::ContextImpl::isPreventingTouchpadTaps() {
1037 // lock is already held by the input loop
1038 return mReader->mPreventingTouchpadTaps;
1039 }
1040
setLastKeyDownTimestamp(nsecs_t when)1041 void InputReader::ContextImpl::setLastKeyDownTimestamp(nsecs_t when) {
1042 mReader->mLastKeyDownTimestamp = when;
1043 }
1044
getLastKeyDownTimestamp()1045 nsecs_t InputReader::ContextImpl::getLastKeyDownTimestamp() {
1046 return mReader->mLastKeyDownTimestamp;
1047 }
1048
disableVirtualKeysUntil(nsecs_t time)1049 void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
1050 // lock is already held by the input loop
1051 mReader->disableVirtualKeysUntilLocked(time);
1052 }
1053
shouldDropVirtualKey(nsecs_t now,int32_t keyCode,int32_t scanCode)1054 bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now, int32_t keyCode,
1055 int32_t scanCode) {
1056 // lock is already held by the input loop
1057 return mReader->shouldDropVirtualKeyLocked(now, keyCode, scanCode);
1058 }
1059
requestTimeoutAtTime(nsecs_t when)1060 void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
1061 // lock is already held by the input loop
1062 mReader->requestTimeoutAtTimeLocked(when);
1063 }
1064
bumpGeneration()1065 int32_t InputReader::ContextImpl::bumpGeneration() {
1066 // lock is already held by the input loop
1067 return mReader->bumpGenerationLocked();
1068 }
1069
getExternalStylusDevices(std::vector<InputDeviceInfo> & outDevices)1070 void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
1071 // lock is already held by whatever called refreshConfigurationLocked
1072 mReader->getExternalStylusDevicesLocked(outDevices);
1073 }
1074
dispatchExternalStylusState(const StylusState & state)1075 std::list<NotifyArgs> InputReader::ContextImpl::dispatchExternalStylusState(
1076 const StylusState& state) {
1077 return mReader->dispatchExternalStylusStateLocked(state);
1078 }
1079
getPolicy()1080 InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
1081 return mReader->mPolicy.get();
1082 }
1083
getEventHub()1084 EventHubInterface* InputReader::ContextImpl::getEventHub() {
1085 return mReader->mEventHub.get();
1086 }
1087
getNextId()1088 int32_t InputReader::ContextImpl::getNextId() {
1089 return mIdGenerator.nextId();
1090 }
1091
getKeyboardClassifier()1092 KeyboardClassifier& InputReader::ContextImpl::getKeyboardClassifier() {
1093 return *mReader->mKeyboardClassifier;
1094 }
1095
1096 } // namespace android
1097