1 /*
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
21 #include "InputMapper.h"
22
23 namespace android {
24
InputDevice(InputReaderContext * context,int32_t id,int32_t generation,int32_t controllerNumber,const InputDeviceIdentifier & identifier,uint32_t classes)25 InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
26 int32_t controllerNumber, const InputDeviceIdentifier& identifier,
27 uint32_t classes)
28 : mContext(context),
29 mId(id),
30 mGeneration(generation),
31 mControllerNumber(controllerNumber),
32 mIdentifier(identifier),
33 mClasses(classes),
34 mSources(0),
35 mIsExternal(false),
36 mHasMic(false),
37 mDropUntilNextSync(false) {}
38
~InputDevice()39 InputDevice::~InputDevice() {
40 size_t numMappers = mMappers.size();
41 for (size_t i = 0; i < numMappers; i++) {
42 delete mMappers[i];
43 }
44 mMappers.clear();
45 }
46
isEnabled()47 bool InputDevice::isEnabled() {
48 return getEventHub()->isDeviceEnabled(mId);
49 }
50
setEnabled(bool enabled,nsecs_t when)51 void InputDevice::setEnabled(bool enabled, nsecs_t when) {
52 if (isEnabled() == enabled) {
53 return;
54 }
55
56 if (enabled) {
57 getEventHub()->enableDevice(mId);
58 reset(when);
59 } else {
60 reset(when);
61 getEventHub()->disableDevice(mId);
62 }
63 // Must change generation to flag this device as changed
64 bumpGeneration();
65 }
66
dump(std::string & dump)67 void InputDevice::dump(std::string& dump) {
68 InputDeviceInfo deviceInfo;
69 getDeviceInfo(&deviceInfo);
70
71 dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
72 deviceInfo.getDisplayName().c_str());
73 dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
74 dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
75 dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
76 if (mAssociatedDisplayPort) {
77 dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
78 } else {
79 dump += "<none>\n";
80 }
81 dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
82 dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
83 dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
84
85 const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
86 if (!ranges.empty()) {
87 dump += INDENT2 "Motion Ranges:\n";
88 for (size_t i = 0; i < ranges.size(); i++) {
89 const InputDeviceInfo::MotionRange& range = ranges[i];
90 const char* label = getAxisLabel(range.axis);
91 char name[32];
92 if (label) {
93 strncpy(name, label, sizeof(name));
94 name[sizeof(name) - 1] = '\0';
95 } else {
96 snprintf(name, sizeof(name), "%d", range.axis);
97 }
98 dump += StringPrintf(INDENT3
99 "%s: source=0x%08x, "
100 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
101 name, range.source, range.min, range.max, range.flat, range.fuzz,
102 range.resolution);
103 }
104 }
105
106 size_t numMappers = mMappers.size();
107 for (size_t i = 0; i < numMappers; i++) {
108 InputMapper* mapper = mMappers[i];
109 mapper->dump(dump);
110 }
111 }
112
addMapper(InputMapper * mapper)113 void InputDevice::addMapper(InputMapper* mapper) {
114 mMappers.push_back(mapper);
115 }
116
configure(nsecs_t when,const InputReaderConfiguration * config,uint32_t changes)117 void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
118 uint32_t changes) {
119 mSources = 0;
120
121 if (!isIgnored()) {
122 if (!changes) { // first time only
123 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
124 }
125
126 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
127 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
128 sp<KeyCharacterMap> keyboardLayout =
129 mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
130 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
131 bumpGeneration();
132 }
133 }
134 }
135
136 if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
137 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
138 std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
139 if (mAlias != alias) {
140 mAlias = alias;
141 bumpGeneration();
142 }
143 }
144 }
145
146 if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
147 ssize_t index = config->disabledDevices.indexOf(mId);
148 bool enabled = index < 0;
149 setEnabled(enabled, when);
150 }
151
152 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
153 // In most situations, no port will be specified.
154 mAssociatedDisplayPort = std::nullopt;
155 // Find the display port that corresponds to the current input port.
156 const std::string& inputPort = mIdentifier.location;
157 if (!inputPort.empty()) {
158 const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
159 const auto& displayPort = ports.find(inputPort);
160 if (displayPort != ports.end()) {
161 mAssociatedDisplayPort = std::make_optional(displayPort->second);
162 }
163 }
164 }
165
166 for (InputMapper* mapper : mMappers) {
167 mapper->configure(when, config, changes);
168 mSources |= mapper->getSources();
169 }
170 }
171 }
172
reset(nsecs_t when)173 void InputDevice::reset(nsecs_t when) {
174 for (InputMapper* mapper : mMappers) {
175 mapper->reset(when);
176 }
177
178 mContext->updateGlobalMetaState();
179
180 notifyReset(when);
181 }
182
process(const RawEvent * rawEvents,size_t count)183 void InputDevice::process(const RawEvent* rawEvents, size_t count) {
184 // Process all of the events in order for each mapper.
185 // We cannot simply ask each mapper to process them in bulk because mappers may
186 // have side-effects that must be interleaved. For example, joystick movement events and
187 // gamepad button presses are handled by different mappers but they should be dispatched
188 // in the order received.
189 for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
190 #if DEBUG_RAW_EVENTS
191 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
192 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
193 #endif
194
195 if (mDropUntilNextSync) {
196 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
197 mDropUntilNextSync = false;
198 #if DEBUG_RAW_EVENTS
199 ALOGD("Recovered from input event buffer overrun.");
200 #endif
201 } else {
202 #if DEBUG_RAW_EVENTS
203 ALOGD("Dropped input event while waiting for next input sync.");
204 #endif
205 }
206 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
207 ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
208 mDropUntilNextSync = true;
209 reset(rawEvent->when);
210 } else {
211 for (InputMapper* mapper : mMappers) {
212 mapper->process(rawEvent);
213 }
214 }
215 --count;
216 }
217 }
218
timeoutExpired(nsecs_t when)219 void InputDevice::timeoutExpired(nsecs_t when) {
220 for (InputMapper* mapper : mMappers) {
221 mapper->timeoutExpired(when);
222 }
223 }
224
updateExternalStylusState(const StylusState & state)225 void InputDevice::updateExternalStylusState(const StylusState& state) {
226 for (InputMapper* mapper : mMappers) {
227 mapper->updateExternalStylusState(state);
228 }
229 }
230
getDeviceInfo(InputDeviceInfo * outDeviceInfo)231 void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
232 outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
233 mHasMic);
234 for (InputMapper* mapper : mMappers) {
235 mapper->populateDeviceInfo(outDeviceInfo);
236 }
237 }
238
getKeyCodeState(uint32_t sourceMask,int32_t keyCode)239 int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
240 return getState(sourceMask, keyCode, &InputMapper::getKeyCodeState);
241 }
242
getScanCodeState(uint32_t sourceMask,int32_t scanCode)243 int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
244 return getState(sourceMask, scanCode, &InputMapper::getScanCodeState);
245 }
246
getSwitchState(uint32_t sourceMask,int32_t switchCode)247 int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
248 return getState(sourceMask, switchCode, &InputMapper::getSwitchState);
249 }
250
getState(uint32_t sourceMask,int32_t code,GetStateFunc getStateFunc)251 int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
252 int32_t result = AKEY_STATE_UNKNOWN;
253 for (InputMapper* mapper : mMappers) {
254 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
255 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
256 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
257 int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
258 if (currentResult >= AKEY_STATE_DOWN) {
259 return currentResult;
260 } else if (currentResult == AKEY_STATE_UP) {
261 result = currentResult;
262 }
263 }
264 }
265 return result;
266 }
267
markSupportedKeyCodes(uint32_t sourceMask,size_t numCodes,const int32_t * keyCodes,uint8_t * outFlags)268 bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
269 const int32_t* keyCodes, uint8_t* outFlags) {
270 bool result = false;
271 for (InputMapper* mapper : mMappers) {
272 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
273 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
274 }
275 }
276 return result;
277 }
278
vibrate(const nsecs_t * pattern,size_t patternSize,ssize_t repeat,int32_t token)279 void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
280 int32_t token) {
281 for (InputMapper* mapper : mMappers) {
282 mapper->vibrate(pattern, patternSize, repeat, token);
283 }
284 }
285
cancelVibrate(int32_t token)286 void InputDevice::cancelVibrate(int32_t token) {
287 for (InputMapper* mapper : mMappers) {
288 mapper->cancelVibrate(token);
289 }
290 }
291
cancelTouch(nsecs_t when)292 void InputDevice::cancelTouch(nsecs_t when) {
293 for (InputMapper* mapper : mMappers) {
294 mapper->cancelTouch(when);
295 }
296 }
297
getMetaState()298 int32_t InputDevice::getMetaState() {
299 int32_t result = 0;
300 for (InputMapper* mapper : mMappers) {
301 result |= mapper->getMetaState();
302 }
303 return result;
304 }
305
updateMetaState(int32_t keyCode)306 void InputDevice::updateMetaState(int32_t keyCode) {
307 for (InputMapper* mapper : mMappers) {
308 mapper->updateMetaState(keyCode);
309 }
310 }
311
fadePointer()312 void InputDevice::fadePointer() {
313 for (InputMapper* mapper : mMappers) {
314 mapper->fadePointer();
315 }
316 }
317
bumpGeneration()318 void InputDevice::bumpGeneration() {
319 mGeneration = mContext->bumpGeneration();
320 }
321
notifyReset(nsecs_t when)322 void InputDevice::notifyReset(nsecs_t when) {
323 NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
324 mContext->getListener()->notifyDeviceReset(&args);
325 }
326
getAssociatedDisplay()327 std::optional<int32_t> InputDevice::getAssociatedDisplay() {
328 for (InputMapper* mapper : mMappers) {
329 std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
330 if (associatedDisplayId) {
331 return associatedDisplayId;
332 }
333 }
334
335 return std::nullopt;
336 }
337
338 } // namespace android
339