1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
|
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <bitset>
#include <climits>
#include <filesystem>
#include <functional>
#include <map>
#include <ostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <batteryservice/BatteryService.h>
#include <ftl/flags.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/KeyCharacterMap.h>
#include <input/KeyLayoutMap.h>
#include <input/Keyboard.h>
#include <input/PropertyMap.h>
#include <input/VirtualKeyMap.h>
#include <linux/input.h>
#include <sys/epoll.h>
#include <utils/BitSet.h>
#include <utils/Errors.h>
#include <utils/List.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
#include "TouchVideoDevice.h"
#include "VibrationElement.h"
struct inotify_event;
namespace android {
/* Number of colors : {red, green, blue} */
static constexpr size_t COLOR_NUM = 3;
/*
* A raw event as retrieved from the EventHub.
*/
struct RawEvent {
// Time when the event happened
nsecs_t when;
// Time when the event was read by EventHub. Only populated for input events.
// For other events (device added/removed/etc), this value is undefined and should not be read.
nsecs_t readTime;
int32_t deviceId;
int32_t type;
int32_t code;
int32_t value;
};
/* Describes an absolute axis. */
struct RawAbsoluteAxisInfo {
bool valid{false}; // true if the information is valid, false otherwise
int32_t minValue{}; // minimum value
int32_t maxValue{}; // maximum value
int32_t flat{}; // center flat position, eg. flat == 8 means center is between -8 and 8
int32_t fuzz{}; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
int32_t resolution{}; // resolution in units per mm or radians per mm
inline void clear() { *this = RawAbsoluteAxisInfo(); }
};
std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info);
/*
* Input device classes.
*/
enum class InputDeviceClass : uint32_t {
/* The input device is a keyboard or has buttons. */
KEYBOARD = 0x00000001,
/* The input device is an alpha-numeric keyboard (not just a dial pad). */
ALPHAKEY = 0x00000002,
/* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
TOUCH = 0x00000004,
/* The input device is a cursor device such as a trackball or mouse. */
CURSOR = 0x00000008,
/* The input device is a multi-touch touchscreen or touchpad. */
TOUCH_MT = 0x00000010,
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
DPAD = 0x00000020,
/* The input device is a gamepad (implies keyboard, has BUTTON keys). */
GAMEPAD = 0x00000040,
/* The input device has switches. */
SWITCH = 0x00000080,
/* The input device is a joystick (implies gamepad, has joystick absolute axes). */
JOYSTICK = 0x00000100,
/* The input device has a vibrator (supports FF_RUMBLE). */
VIBRATOR = 0x00000200,
/* The input device has a microphone. */
MIC = 0x00000400,
/* The input device is an external stylus (has data we want to fuse with touch data). */
EXTERNAL_STYLUS = 0x00000800,
/* The input device has a rotary encoder */
ROTARY_ENCODER = 0x00001000,
/* The input device has a sensor like accelerometer, gyro, etc */
SENSOR = 0x00002000,
/* The input device has a battery */
BATTERY = 0x00004000,
/* The input device has sysfs controllable lights */
LIGHT = 0x00008000,
/* The input device is a touchpad, requiring an on-screen cursor. */
TOUCHPAD = 0x00010000,
/* The input device is virtual (not a real device, not part of UI configuration). */
VIRTUAL = 0x40000000,
/* The input device is external (not built-in). */
EXTERNAL = 0x80000000,
};
enum class SysfsClass : uint32_t {
POWER_SUPPLY = 0,
LEDS = 1,
ftl_last = LEDS
};
enum class LightColor : uint32_t {
RED = 0,
GREEN = 1,
BLUE = 2,
};
enum class InputLightClass : uint32_t {
/* The input light has brightness node. */
BRIGHTNESS = 0x00000001,
/* The input light has red name. */
RED = 0x00000002,
/* The input light has green name. */
GREEN = 0x00000004,
/* The input light has blue name. */
BLUE = 0x00000008,
/* The input light has global name. */
GLOBAL = 0x00000010,
/* The input light has multi index node. */
MULTI_INDEX = 0x00000020,
/* The input light has multi intensity node. */
MULTI_INTENSITY = 0x00000040,
/* The input light has max brightness node. */
MAX_BRIGHTNESS = 0x00000080,
/* The input light has kbd_backlight name */
KEYBOARD_BACKLIGHT = 0x00000100,
};
enum class InputBatteryClass : uint32_t {
/* The input device battery has capacity node. */
CAPACITY = 0x00000001,
/* The input device battery has capacity_level node. */
CAPACITY_LEVEL = 0x00000002,
/* The input device battery has status node. */
STATUS = 0x00000004,
};
/* Describes a raw light. */
struct RawLightInfo {
int32_t id;
std::string name;
std::optional<int32_t> maxBrightness;
ftl::Flags<InputLightClass> flags;
std::array<int32_t, COLOR_NUM> rgbIndex;
std::filesystem::path path;
bool operator==(const RawLightInfo&) const = default;
bool operator!=(const RawLightInfo&) const = default;
};
/* Describes a raw battery. */
struct RawBatteryInfo {
int32_t id;
std::string name;
ftl::Flags<InputBatteryClass> flags;
std::filesystem::path path;
bool operator==(const RawBatteryInfo&) const = default;
bool operator!=(const RawBatteryInfo&) const = default;
};
/* Layout information associated with the device */
struct RawLayoutInfo {
std::string languageTag;
std::string layoutType;
bool operator==(const RawLayoutInfo&) const = default;
bool operator!=(const RawLayoutInfo&) const = default;
};
/*
* Gets the class that owns an axis, in cases where multiple classes might claim
* the same axis for different purposes.
*/
extern ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis,
ftl::Flags<InputDeviceClass> deviceClasses);
/*
* Grand Central Station for events.
*
* The event hub aggregates input events received across all known input
* devices on the system, including devices that may be emulated by the simulator
* environment. In addition, the event hub generates fake input events to indicate
* when devices are added or removed.
*
* The event hub provides a stream of input events (via the getEvent function).
* It also supports querying the current actual state of input devices such as identifying
* which keys are currently down. Finally, the event hub keeps track of the capabilities of
* individual input devices, such as their class and the set of key codes that they support.
*/
class EventHubInterface {
public:
EventHubInterface() {}
virtual ~EventHubInterface() {}
// Synthetic raw event type codes produced when devices are added or removed.
enum {
// Sent when a device is added.
DEVICE_ADDED = 0x10000000,
// Sent when a device is removed.
DEVICE_REMOVED = 0x20000000,
// Sent when all added/removed devices from the most recent scan have been reported.
// This event is always sent at least once.
FINISHED_DEVICE_SCAN = 0x30000000,
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
};
virtual ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const = 0;
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
virtual int32_t getDeviceControllerNumber(int32_t deviceId) const = 0;
/**
* Get the PropertyMap for the provided EventHub device, if available.
* This acquires the device lock, so a copy is returned rather than the raw pointer
* to the device's PropertyMap. A std::nullopt may be returned if the device could
* not be found, or if it doesn't have any configuration.
*/
virtual std::optional<PropertyMap> getConfiguration(int32_t deviceId) const = 0;
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const = 0;
virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0;
virtual bool hasInputProperty(int32_t deviceId, int property) const = 0;
virtual bool hasMscEvent(int32_t deviceId, int mscEvent) const = 0;
virtual void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode,
int32_t toKeyCode) const = 0;
virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
int32_t metaState, int32_t* outKeycode, int32_t* outMetaState,
uint32_t* outFlags) const = 0;
virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const = 0;
// Sets devices that are excluded from opening.
// This can be used to ignore input devices for sensors.
virtual void setExcludedDevices(const std::vector<std::string>& devices) = 0;
/*
* Wait for events to become available and returns them.
* After returning, the EventHub holds onto a wake lock until the next call to getEvent.
* This ensures that the device will not go to sleep while the event is being processed.
* If the device needs to remain awake longer than that, then the caller is responsible
* for taking care of it (say, by poking the power manager user activity timer).
*
* The timeout is advisory only. If the device is asleep, it will not wake just to
* service the timeout.
*
* Returns the number of events obtained, or 0 if the timeout expired.
*/
virtual std::vector<RawEvent> getEvents(int timeoutMillis) = 0;
virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
int32_t deviceId, int32_t absCode) const = 0;
// Raw batteries are sysfs power_supply nodes we found from the EventHub device sysfs node,
// containing the raw info of the sysfs node structure.
virtual std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const = 0;
virtual std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId,
int32_t BatteryId) const = 0;
// Raw lights are sysfs led light nodes we found from the EventHub device sysfs node,
// containing the raw info of the sysfs node structure.
virtual std::vector<int32_t> getRawLightIds(int32_t deviceId) const = 0;
virtual std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId,
int32_t lightId) const = 0;
virtual std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const = 0;
virtual void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) = 0;
virtual std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
int32_t deviceId, int32_t lightId) const = 0;
virtual void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) = 0;
/* Query Layout info associated with the input device. */
virtual std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const = 0;
/* Query current input state. */
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
int32_t* outValue) const = 0;
/* Query Multi-Touch slot values for an axis. Returns error or an 1 indexed array of size
* (slotCount + 1). The value at the 0 index is set to queried axis. */
virtual base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
size_t slotCount) const = 0;
virtual int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const = 0;
/*
* Examine key input devices for specific framework keycode support
*/
virtual bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const = 0;
virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
virtual bool hasKeyCode(int32_t deviceId, int32_t keyCode) const = 0;
/* LED related functions expect Android LED constants, not scan codes or HID usages */
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
virtual void getVirtualKeyDefinitions(
int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
virtual const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const = 0;
virtual bool setKeyboardLayoutOverlay(int32_t deviceId,
std::shared_ptr<KeyCharacterMap> map) = 0;
/* Control the vibrator. */
virtual void vibrate(int32_t deviceId, const VibrationElement& effect) = 0;
virtual void cancelVibrate(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) const = 0;
/* Query battery level. */
virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId,
int32_t batteryId) const = 0;
/* Query battery status. */
virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId, int32_t batteryId) const = 0;
/* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
virtual void requestReopenDevices() = 0;
/* Wakes up getEvents() if it is blocked on a read. */
virtual void wake() = 0;
/* Dump EventHub state to a string. */
virtual void dump(std::string& dump) const = 0;
/* Called by the heatbeat to ensures that the reader has not deadlocked. */
virtual void monitor() const = 0;
/* Return true if the device is enabled. */
virtual bool isDeviceEnabled(int32_t deviceId) const = 0;
/* Enable an input device */
virtual status_t enableDevice(int32_t deviceId) = 0;
/* Disable an input device. Closes file descriptor to that device. */
virtual status_t disableDevice(int32_t deviceId) = 0;
/* Sysfs node changed. Reopen the Eventhub device if any new Peripheral like Light, Battery,
* etc. is detected. */
virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
};
template <std::size_t BITS>
class BitArray {
/* Array element type and vector of element type. */
using Element = std::uint32_t;
/* Number of bits in each BitArray element. */
static constexpr size_t WIDTH = sizeof(Element) * CHAR_BIT;
/* Number of elements to represent a bit array of the specified size of bits. */
static constexpr size_t COUNT = (BITS + WIDTH - 1) / WIDTH;
public:
/* BUFFER type declaration for BitArray */
using Buffer = std::array<Element, COUNT>;
/* To tell if a bit is set in array, it selects an element from the array, and test
* if the relevant bit set.
* Note the parameter "bit" is an index to the bit, 0 <= bit < BITS.
*/
inline bool test(size_t bit) const {
return (bit < BITS) && mData[bit / WIDTH].test(bit % WIDTH);
}
/* Sets the given bit in the bit array to given value.
* Returns true if the given bit is a valid index and thus was set successfully.
*/
inline bool set(size_t bit, bool value) {
if (bit >= BITS) {
return false;
}
mData[bit / WIDTH].set(bit % WIDTH, value);
return true;
}
/* Returns total number of bytes needed for the array */
inline size_t bytes() { return (BITS + CHAR_BIT - 1) / CHAR_BIT; }
/* Returns true if array contains any non-zero bit from the range defined by start and end
* bit index [startIndex, endIndex).
*/
bool any(size_t startIndex, size_t endIndex) {
if (startIndex >= endIndex || startIndex > BITS || endIndex > BITS + 1) {
ALOGE("Invalid start/end index. start = %zu, end = %zu, total bits = %zu", startIndex,
endIndex, BITS);
return false;
}
size_t se = startIndex / WIDTH; // Start of element
size_t ee = endIndex / WIDTH; // End of element
size_t si = startIndex % WIDTH; // Start index in start element
size_t ei = endIndex % WIDTH; // End index in end element
// Need to check first unaligned bitset for any non zero bit
if (si > 0) {
size_t nBits = se == ee ? ei - si : WIDTH - si;
// Generate the mask of interested bit range
Element mask = ((1 << nBits) - 1) << si;
if (mData[se++].to_ulong() & mask) {
return true;
}
}
// Check whole bitset for any bit set
for (; se < ee; se++) {
if (mData[se].any()) {
return true;
}
}
// Need to check last unaligned bitset for any non zero bit
if (ei > 0 && se <= ee) {
// Generate the mask of interested bit range
Element mask = (1 << ei) - 1;
if (mData[se].to_ulong() & mask) {
return true;
}
}
return false;
}
/* Load bit array values from buffer */
void loadFromBuffer(const Buffer& buffer) {
for (size_t i = 0; i < COUNT; i++) {
mData[i] = std::bitset<WIDTH>(buffer[i]);
}
}
/* Dump the indices in the bit array that are set. */
inline std::string dumpSetIndices(std::string separator,
std::function<std::string(size_t /*index*/)> format) {
std::string dmp;
for (size_t i = 0; i < BITS; i++) {
if (test(i)) {
if (!dmp.empty()) {
dmp += separator;
}
dmp += format(i);
}
}
return dmp.empty() ? "<none>" : dmp;
}
private:
std::array<std::bitset<WIDTH>, COUNT> mData;
};
class EventHub : public EventHubInterface {
public:
EventHub();
ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override final;
InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override final;
int32_t getDeviceControllerNumber(int32_t deviceId) const override final;
std::optional<PropertyMap> getConfiguration(int32_t deviceId) const override final;
status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const override final;
bool hasRelativeAxis(int32_t deviceId, int axis) const override final;
bool hasInputProperty(int32_t deviceId, int property) const override final;
bool hasMscEvent(int32_t deviceId, int mscEvent) const override final;
void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode,
int32_t toKeyCode) const override final;
status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
int32_t* outKeycode, int32_t* outMetaState,
uint32_t* outFlags) const override final;
status_t mapAxis(int32_t deviceId, int32_t scanCode,
AxisInfo* outAxisInfo) const override final;
base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
int32_t deviceId, int32_t absCode) const override final;
std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override final;
std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId,
int32_t BatteryId) const override final;
std::vector<int32_t> getRawLightIds(int32_t deviceId) const override final;
std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId,
int32_t lightId) const override final;
std::optional<int32_t> getLightBrightness(int32_t deviceId,
int32_t lightId) const override final;
void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override final;
std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
int32_t deviceId, int32_t lightId) const override final;
void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) override final;
std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const override final;
void setExcludedDevices(const std::vector<std::string>& devices) override final;
int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final;
int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override final;
int32_t getSwitchState(int32_t deviceId, int32_t sw) const override final;
int32_t getKeyCodeForKeyLocation(int32_t deviceId,
int32_t locationKeyCode) const override final;
status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
int32_t* outValue) const override final;
base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
size_t slotCount) const override final;
bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const override final;
std::vector<RawEvent> getEvents(int timeoutMillis) override final;
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override final;
bool hasScanCode(int32_t deviceId, int32_t scanCode) const override final;
bool hasKeyCode(int32_t deviceId, int32_t keyCode) const override final;
bool hasLed(int32_t deviceId, int32_t led) const override final;
void setLedState(int32_t deviceId, int32_t led, bool on) override final;
void getVirtualKeyDefinitions(
int32_t deviceId,
std::vector<VirtualKeyDefinition>& outVirtualKeys) const override final;
const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(
int32_t deviceId) const override final;
bool setKeyboardLayoutOverlay(int32_t deviceId,
std::shared_ptr<KeyCharacterMap> map) override final;
void vibrate(int32_t deviceId, const VibrationElement& effect) override final;
void cancelVibrate(int32_t deviceId) override final;
std::vector<int32_t> getVibratorIds(int32_t deviceId) const override final;
void requestReopenDevices() override final;
void wake() override final;
void dump(std::string& dump) const override final;
void monitor() const override final;
std::optional<int32_t> getBatteryCapacity(int32_t deviceId,
int32_t batteryId) const override final;
std::optional<int32_t> getBatteryStatus(int32_t deviceId,
int32_t batteryId) const override final;
bool isDeviceEnabled(int32_t deviceId) const override final;
status_t enableDevice(int32_t deviceId) override final;
status_t disableDevice(int32_t deviceId) override final;
void sysfsNodeChanged(const std::string& sysfsNodePath) override final;
~EventHub() override;
private:
// Holds information about the sysfs device associated with the Device.
struct AssociatedDevice {
// The sysfs root path of the misc device.
std::filesystem::path sysfsRootPath;
std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos;
std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos;
std::optional<RawLayoutInfo> layoutInfo;
bool isChanged() const;
bool operator==(const AssociatedDevice&) const = default;
bool operator!=(const AssociatedDevice&) const = default;
std::string dump() const;
};
struct Device {
int fd; // may be -1 if device is closed
const int32_t id;
const std::string path;
const InputDeviceIdentifier identifier;
std::unique_ptr<TouchVideoDevice> videoDevice;
ftl::Flags<InputDeviceClass> classes;
BitArray<KEY_CNT> keyBitmask;
BitArray<KEY_CNT> keyState;
BitArray<REL_CNT> relBitmask;
BitArray<SW_CNT> swBitmask;
BitArray<SW_CNT> swState;
BitArray<LED_CNT> ledBitmask;
BitArray<FF_CNT> ffBitmask;
BitArray<INPUT_PROP_CNT> propBitmask;
BitArray<MSC_CNT> mscBitmask;
BitArray<ABS_CNT> absBitmask;
struct AxisState {
RawAbsoluteAxisInfo info;
int value;
};
std::map<int /*axis*/, AxisState> absState;
std::string configurationFile;
std::unique_ptr<PropertyMap> configuration;
std::unique_ptr<VirtualKeyMap> virtualKeyMap;
KeyMap keyMap;
bool ffEffectPlaying;
int16_t ffEffectId; // initially -1
// A shared_ptr of a device associated with the input device.
// The input devices that have the same sysfs path have the same associated device.
std::shared_ptr<const AssociatedDevice> associatedDevice;
int32_t controllerNumber;
Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier,
std::shared_ptr<const AssociatedDevice> assocDev);
~Device();
void close();
bool enabled; // initially true
status_t enable();
status_t disable();
bool hasValidFd() const;
const bool isVirtual; // set if fd < 0 is passed to constructor
const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap() const;
template <std::size_t N>
status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray);
void configureFd();
void populateAbsoluteAxisStates();
bool hasKeycodeLocked(int keycode) const;
void loadConfigurationLocked();
bool loadVirtualKeyMapLocked();
status_t loadKeyMapLocked();
bool isExternalDeviceLocked();
bool deviceHasMicLocked();
void setLedForControllerLocked();
status_t mapLed(int32_t led, int32_t* outScanCode) const;
void setLedStateLocked(int32_t led, bool on);
bool currentFrameDropped;
void trackInputEvent(const struct input_event& event);
void readDeviceState();
};
/**
* Create a new device for the provided path.
*/
void openDeviceLocked(const std::string& devicePath) REQUIRES(mLock);
void openVideoDeviceLocked(const std::string& devicePath) REQUIRES(mLock);
/**
* Try to associate a video device with an input device. If the association succeeds,
* the videoDevice is moved into the input device. 'videoDevice' will become null if this
* happens.
* Return true if the association succeeds.
* Return false otherwise.
*/
bool tryAddVideoDeviceLocked(Device& device, std::unique_ptr<TouchVideoDevice>& videoDevice)
REQUIRES(mLock);
void createVirtualKeyboardLocked() REQUIRES(mLock);
void addDeviceLocked(std::unique_ptr<Device> device) REQUIRES(mLock);
void assignDescriptorLocked(InputDeviceIdentifier& identifier) REQUIRES(mLock);
std::shared_ptr<const AssociatedDevice> obtainAssociatedDeviceLocked(
const std::filesystem::path& devicePath) const REQUIRES(mLock);
void closeDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock);
void closeVideoDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock);
void closeDeviceLocked(Device& device) REQUIRES(mLock);
void closeAllDevicesLocked() REQUIRES(mLock);
status_t registerFdForEpoll(int fd);
status_t unregisterFdFromEpoll(int fd);
status_t registerDeviceForEpollLocked(Device& device) REQUIRES(mLock);
void registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) REQUIRES(mLock);
status_t unregisterDeviceFromEpollLocked(Device& device) REQUIRES(mLock);
void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) REQUIRES(mLock);
status_t scanDirLocked(const std::string& dirname) REQUIRES(mLock);
status_t scanVideoDirLocked(const std::string& dirname) REQUIRES(mLock);
void scanDevicesLocked() REQUIRES(mLock);
base::Result<void> readNotifyLocked() REQUIRES(mLock);
void handleNotifyEventLocked(const inotify_event&) REQUIRES(mLock);
Device* getDeviceLocked(int32_t deviceId) const REQUIRES(mLock);
Device* getDeviceByPathLocked(const std::string& devicePath) const REQUIRES(mLock);
/**
* Look through all available fd's (both for input devices and for video devices),
* and return the device pointer.
*/
Device* getDeviceByFdLocked(int fd) const REQUIRES(mLock);
int32_t getNextControllerNumberLocked(const std::string& name) REQUIRES(mLock);
bool hasDeviceWithDescriptorLocked(const std::string& descriptor) const REQUIRES(mLock);
void releaseControllerNumberLocked(int32_t num) REQUIRES(mLock);
void reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier,
ftl::Flags<InputDeviceClass> classes) REQUIRES(mLock);
const std::unordered_map<int32_t, RawBatteryInfo>& getBatteryInfoLocked(int32_t deviceId) const
REQUIRES(mLock);
const std::unordered_map<int32_t, RawLightInfo>& getLightInfoLocked(int32_t deviceId) const
REQUIRES(mLock);
void addDeviceInputInotify();
void addDeviceInotify();
// Protect all internal state.
mutable std::mutex mLock;
// The actual id of the built-in keyboard, or NO_BUILT_IN_KEYBOARD if none.
// EventHub remaps the built-in keyboard to id 0 externally as required by the API.
enum {
// Must not conflict with any other assigned device ids, including
// the virtual keyboard id (-1).
NO_BUILT_IN_KEYBOARD = -2,
};
int32_t mBuiltInKeyboardId;
int32_t mNextDeviceId;
BitSet32 mControllerNumbers;
std::unordered_map<int32_t, std::unique_ptr<Device>> mDevices;
/**
* Video devices that report touchscreen heatmap, but have not (yet) been paired
* with a specific input device. Video device discovery is independent from input device
* discovery, so the two types of devices could be found in any order.
* Ideally, video devices in this queue do not have an open fd, or at least aren't
* actively streaming.
*/
std::vector<std::unique_ptr<TouchVideoDevice>> mUnattachedVideoDevices;
std::vector<std::unique_ptr<Device>> mOpeningDevices;
std::vector<std::unique_ptr<Device>> mClosingDevices;
bool mNeedToSendFinishedDeviceScan;
bool mNeedToReopenDevices;
bool mNeedToScanDevices;
std::vector<std::string> mExcludedDevices;
int mEpollFd;
int mINotifyFd;
int mWakeReadPipeFd;
int mWakeWritePipeFd;
int mDeviceInputWd;
int mDeviceWd = -1;
// Maximum number of signalled FDs to handle at a time.
static const int EPOLL_MAX_EVENTS = 16;
// The array of pending epoll events and the index of the next event to be handled.
struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
size_t mPendingEventCount;
size_t mPendingEventIndex;
bool mPendingINotify;
};
} // namespace android
|