blob: ae82cd4aa45b522ff55a79d966d8479ccae924b0 [file] [log] [blame]
Prabir Pradhanbaa5c822019-08-30 15:27:05 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Macros.h"
18
19#include "InputDevice.h"
20
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -080021#include "CursorInputMapper.h"
22#include "ExternalStylusInputMapper.h"
23#include "InputReaderContext.h"
24#include "JoystickInputMapper.h"
25#include "KeyboardInputMapper.h"
26#include "MultiTouchInputMapper.h"
27#include "RotaryEncoderInputMapper.h"
28#include "SingleTouchInputMapper.h"
29#include "SwitchInputMapper.h"
30#include "VibratorInputMapper.h"
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070031
32namespace android {
33
34InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
35 int32_t controllerNumber, const InputDeviceIdentifier& identifier,
36 uint32_t classes)
37 : mContext(context),
38 mId(id),
39 mGeneration(generation),
40 mControllerNumber(controllerNumber),
41 mIdentifier(identifier),
42 mClasses(classes),
43 mSources(0),
44 mIsExternal(false),
45 mHasMic(false),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -080046 mDropUntilNextSync(false) {
47 mDeviceContext = std::make_unique<InputDeviceContext>(*this);
48}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070049
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -080050InputDevice::~InputDevice() {}
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070051
52bool InputDevice::isEnabled() {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -080053 return mDeviceContext->isDeviceEnabled();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070054}
55
56void InputDevice::setEnabled(bool enabled, nsecs_t when) {
57 if (enabled && mAssociatedDisplayPort && !mAssociatedViewport) {
58 ALOGW("Cannot enable input device %s because it is associated with port %" PRIu8 ", "
59 "but the corresponding viewport is not found",
60 getName().c_str(), *mAssociatedDisplayPort);
61 enabled = false;
62 }
63
64 if (isEnabled() == enabled) {
65 return;
66 }
67
68 if (enabled) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -080069 mDeviceContext->enableDevice();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070070 reset(when);
71 } else {
72 reset(when);
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -080073 mDeviceContext->disableDevice();
Prabir Pradhanbaa5c822019-08-30 15:27:05 -070074 }
75 // Must change generation to flag this device as changed
76 bumpGeneration();
77}
78
79void InputDevice::dump(std::string& dump) {
80 InputDeviceInfo deviceInfo;
81 getDeviceInfo(&deviceInfo);
82
83 dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
84 deviceInfo.getDisplayName().c_str());
85 dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
86 dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
87 dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
88 if (mAssociatedDisplayPort) {
89 dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
90 } else {
91 dump += "<none>\n";
92 }
93 dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
94 dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
95 dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
96
97 const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
98 if (!ranges.empty()) {
99 dump += INDENT2 "Motion Ranges:\n";
100 for (size_t i = 0; i < ranges.size(); i++) {
101 const InputDeviceInfo::MotionRange& range = ranges[i];
102 const char* label = getAxisLabel(range.axis);
103 char name[32];
104 if (label) {
105 strncpy(name, label, sizeof(name));
106 name[sizeof(name) - 1] = '\0';
107 } else {
108 snprintf(name, sizeof(name), "%d", range.axis);
109 }
110 dump += StringPrintf(INDENT3
111 "%s: source=0x%08x, "
112 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
113 name, range.source, range.min, range.max, range.flat, range.fuzz,
114 range.resolution);
115 }
116 }
117
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800118 for_each_mapper([&dump](InputMapper& mapper) { mapper.dump(dump); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700119}
120
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800121void InputDevice::populateMappers() {
122 uint32_t classes = mClasses;
123 std::vector<std::unique_ptr<InputMapper>>& mappers = mMappers;
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800124 std::unique_ptr<InputDeviceContext>& contextPtr = mDeviceContext;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800125
126 // External devices.
127 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
128 setExternal(true);
129 }
130
131 // Devices with mics.
132 if (classes & INPUT_DEVICE_CLASS_MIC) {
133 setMic(true);
134 }
135
136 // Switch-like devices.
137 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800138 mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800139 }
140
141 // Scroll wheel-like devices.
142 if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800143 mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800144 }
145
146 // Vibrator-like devices.
147 if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800148 mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800149 }
150
151 // Keyboard-like devices.
152 uint32_t keyboardSource = 0;
153 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
154 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
155 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
156 }
157 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
158 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
159 }
160 if (classes & INPUT_DEVICE_CLASS_DPAD) {
161 keyboardSource |= AINPUT_SOURCE_DPAD;
162 }
163 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
164 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
165 }
166
167 if (keyboardSource != 0) {
168 mappers.push_back(
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800169 std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800170 }
171
172 // Cursor-like devices.
173 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800174 mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800175 }
176
177 // Touchscreens and touchpad devices.
178 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800179 mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800180 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800181 mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800182 }
183
184 // Joystick-like devices.
185 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800186 mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800187 }
188
189 // External stylus-like devices.
190 if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800191 mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800192 }
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700193}
194
195void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
196 uint32_t changes) {
197 mSources = 0;
198
199 if (!isIgnored()) {
200 if (!changes) { // first time only
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800201 mDeviceContext->getConfiguration(&mConfiguration);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700202 }
203
204 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
205 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
206 sp<KeyCharacterMap> keyboardLayout =
207 mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800208 if (mDeviceContext->setKeyboardLayoutOverlay(keyboardLayout)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700209 bumpGeneration();
210 }
211 }
212 }
213
214 if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
215 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
216 std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
217 if (mAlias != alias) {
218 mAlias = alias;
219 bumpGeneration();
220 }
221 }
222 }
223
224 if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
225 auto it = config->disabledDevices.find(mId);
226 bool enabled = it == config->disabledDevices.end();
227 setEnabled(enabled, when);
228 }
229
230 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
231 // In most situations, no port will be specified.
232 mAssociatedDisplayPort = std::nullopt;
233 mAssociatedViewport = std::nullopt;
234 // Find the display port that corresponds to the current input port.
235 const std::string& inputPort = mIdentifier.location;
236 if (!inputPort.empty()) {
237 const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
238 const auto& displayPort = ports.find(inputPort);
239 if (displayPort != ports.end()) {
240 mAssociatedDisplayPort = std::make_optional(displayPort->second);
241 }
242 }
243
244 // If the device was explicitly disabled by the user, it would be present in the
245 // "disabledDevices" list. If it is associated with a specific display, and it was not
246 // explicitly disabled, then enable/disable the device based on whether we can find the
247 // corresponding viewport.
248 bool enabled = (config->disabledDevices.find(mId) == config->disabledDevices.end());
249 if (mAssociatedDisplayPort) {
250 mAssociatedViewport = config->getDisplayViewportByPort(*mAssociatedDisplayPort);
251 if (!mAssociatedViewport) {
252 ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
253 "but the corresponding viewport is not found.",
254 getName().c_str(), *mAssociatedDisplayPort);
255 enabled = false;
256 }
257 }
258
259 if (changes) {
260 // For first-time configuration, only allow device to be disabled after mappers have
261 // finished configuring. This is because we need to read some of the properties from
262 // the device's open fd.
263 setEnabled(enabled, when);
264 }
265 }
266
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800267 for_each_mapper([this, when, config, changes](InputMapper& mapper) {
268 mapper.configure(when, config, changes);
269 mSources |= mapper.getSources();
270 });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700271
272 // If a device is just plugged but it might be disabled, we need to update some info like
273 // axis range of touch from each InputMapper first, then disable it.
274 if (!changes) {
275 setEnabled(config->disabledDevices.find(mId) == config->disabledDevices.end(), when);
276 }
277 }
278}
279
280void InputDevice::reset(nsecs_t when) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800281 for_each_mapper([when](InputMapper& mapper) { mapper.reset(when); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700282
283 mContext->updateGlobalMetaState();
284
285 notifyReset(when);
286}
287
288void InputDevice::process(const RawEvent* rawEvents, size_t count) {
289 // Process all of the events in order for each mapper.
290 // We cannot simply ask each mapper to process them in bulk because mappers may
291 // have side-effects that must be interleaved. For example, joystick movement events and
292 // gamepad button presses are handled by different mappers but they should be dispatched
293 // in the order received.
294 for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
295#if DEBUG_RAW_EVENTS
296 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
297 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
298#endif
299
300 if (mDropUntilNextSync) {
301 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
302 mDropUntilNextSync = false;
303#if DEBUG_RAW_EVENTS
304 ALOGD("Recovered from input event buffer overrun.");
305#endif
306 } else {
307#if DEBUG_RAW_EVENTS
308 ALOGD("Dropped input event while waiting for next input sync.");
309#endif
310 }
311 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
312 ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
313 mDropUntilNextSync = true;
314 reset(rawEvent->when);
315 } else {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800316 for_each_mapper([rawEvent](InputMapper& mapper) { mapper.process(rawEvent); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700317 }
318 --count;
319 }
320}
321
322void InputDevice::timeoutExpired(nsecs_t when) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800323 for_each_mapper([when](InputMapper& mapper) { mapper.timeoutExpired(when); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700324}
325
326void InputDevice::updateExternalStylusState(const StylusState& state) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800327 for_each_mapper([state](InputMapper& mapper) { mapper.updateExternalStylusState(state); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700328}
329
330void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
331 outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
332 mHasMic);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800333 for_each_mapper(
334 [outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(outDeviceInfo); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700335}
336
337int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
338 return getState(sourceMask, keyCode, &InputMapper::getKeyCodeState);
339}
340
341int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
342 return getState(sourceMask, scanCode, &InputMapper::getScanCodeState);
343}
344
345int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
346 return getState(sourceMask, switchCode, &InputMapper::getSwitchState);
347}
348
349int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
350 int32_t result = AKEY_STATE_UNKNOWN;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800351 for (auto& mapperPtr : mMappers) {
352 InputMapper& mapper = *mapperPtr;
353 if (sourcesMatchMask(mapper.getSources(), sourceMask)) {
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700354 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
355 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800356 int32_t currentResult = (mapper.*getStateFunc)(sourceMask, code);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700357 if (currentResult >= AKEY_STATE_DOWN) {
358 return currentResult;
359 } else if (currentResult == AKEY_STATE_UP) {
360 result = currentResult;
361 }
362 }
363 }
364 return result;
365}
366
367bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
368 const int32_t* keyCodes, uint8_t* outFlags) {
369 bool result = false;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800370 for_each_mapper([&result, sourceMask, numCodes, keyCodes, outFlags](InputMapper& mapper) {
371 if (sourcesMatchMask(mapper.getSources(), sourceMask)) {
372 result |= mapper.markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700373 }
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800374 });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700375 return result;
376}
377
378void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
379 int32_t token) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800380 for_each_mapper([pattern, patternSize, repeat, token](InputMapper& mapper) {
381 mapper.vibrate(pattern, patternSize, repeat, token);
382 });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700383}
384
385void InputDevice::cancelVibrate(int32_t token) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800386 for_each_mapper([token](InputMapper& mapper) { mapper.cancelVibrate(token); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700387}
388
389void InputDevice::cancelTouch(nsecs_t when) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800390 for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700391}
392
393int32_t InputDevice::getMetaState() {
394 int32_t result = 0;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800395 for_each_mapper([&result](InputMapper& mapper) { result |= mapper.getMetaState(); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700396 return result;
397}
398
399void InputDevice::updateMetaState(int32_t keyCode) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800400 for_each_mapper([keyCode](InputMapper& mapper) { mapper.updateMetaState(keyCode); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700401}
402
403void InputDevice::fadePointer() {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800404 for_each_mapper([](InputMapper& mapper) { mapper.fadePointer(); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700405}
406
407void InputDevice::bumpGeneration() {
408 mGeneration = mContext->bumpGeneration();
409}
410
411void InputDevice::notifyReset(nsecs_t when) {
412 NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
413 mContext->getListener()->notifyDeviceReset(&args);
414}
415
416std::optional<int32_t> InputDevice::getAssociatedDisplayId() {
417 // Check if we had associated to the specific display.
418 if (mAssociatedViewport) {
419 return mAssociatedViewport->displayId;
420 }
421
422 // No associated display port, check if some InputMapper is associated.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800423 return first_in_mappers<int32_t>(
424 [](InputMapper& mapper) { return mapper.getAssociatedDisplayId(); });
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700425}
426
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800427InputDeviceContext::InputDeviceContext(InputDevice& device)
428 : mDevice(device),
429 mContext(device.getContext()),
430 mEventHub(device.getContext()->getEventHub()),
431 mId(device.getId()) {}
432
433InputDeviceContext::~InputDeviceContext() {}
434
Prabir Pradhanbaa5c822019-08-30 15:27:05 -0700435} // namespace android