From a9fd82c447a39ad44a6a4cb908147424e280ba39 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 18 May 2022 09:42:52 -0700 Subject: Do not load keylayout if required kernel module is missing Some key layouts require the presence of a specific kernel module. If the kernel module is not present, the layout should not be loaded. In this CL, we add an option to specify which kernel modules / configs are needed inside the kl file. Bug: 228005926 Test: atest libinput_tests Change-Id: I0d2ab6298bd41df6dc56120bf0385e10da6c3bfe --- libs/input/InputDevice.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'libs/input/InputDevice.cpp') diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 0bee1b6f2a..a9089690b0 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -53,33 +53,39 @@ static void appendInputDeviceConfigurationFileRelativePath(std::string& path, } std::string getInputDeviceConfigurationFilePathByDeviceIdentifier( - const InputDeviceIdentifier& deviceIdentifier, - InputDeviceConfigurationFileType type) { + const InputDeviceIdentifier& deviceIdentifier, InputDeviceConfigurationFileType type, + const char* suffix) { if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { if (deviceIdentifier.version != 0) { // Try vendor product version. - std::string versionPath = getInputDeviceConfigurationFilePathByName( - StringPrintf("Vendor_%04x_Product_%04x_Version_%04x", - deviceIdentifier.vendor, deviceIdentifier.product, - deviceIdentifier.version), - type); + std::string versionPath = + getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%" + "04x_Version_%04x%s", + deviceIdentifier.vendor, + deviceIdentifier.product, + deviceIdentifier.version, + suffix), + type); if (!versionPath.empty()) { return versionPath; } } // Try vendor product. - std::string productPath = getInputDeviceConfigurationFilePathByName( - StringPrintf("Vendor_%04x_Product_%04x", - deviceIdentifier.vendor, deviceIdentifier.product), - type); + std::string productPath = + getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%04x%s", + deviceIdentifier.vendor, + deviceIdentifier.product, + suffix), + type); if (!productPath.empty()) { return productPath; } } // Try device name. - return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName(), type); + return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName() + suffix, + type); } std::string getInputDeviceConfigurationFilePathByName( -- cgit v1.2.3-59-g8ed1b From dd82b8ebbd271b5f48f8bbc620a9f5b549b0905e Mon Sep 17 00:00:00 2001 From: Vaibhav Devmurari Date: Tue, 16 Aug 2022 15:34:01 +0000 Subject: Fetch country code information from Device sysfs path HID devices report the country code via sysfs. Need to read it and pass it and save it as a member variable to InputDevice In subsequent CLs will use it to auto-detect a layout for PK. More information in DD: go/pk_auto_layout_detection Test: atest inputflinger_tests:InputReaderTest Bug: 242715614 Change-Id: I73ca7518dbee3e563c41024bb3ed41261c8d7846 --- include/input/InputDevice.h | 11 +- libs/input/Android.bp | 1 + libs/input/InputDevice.cpp | 7 +- .../hardware/input/InputDeviceCountryCode.aidl | 212 +++++++++++++++++++++ services/inputflinger/reader/EventHub.cpp | 32 ++++ services/inputflinger/reader/InputDevice.cpp | 15 +- services/inputflinger/reader/include/EventHub.h | 11 +- services/inputflinger/reader/include/InputDevice.h | 4 + services/inputflinger/tests/InputReader_test.cpp | 28 +++ 9 files changed, 312 insertions(+), 9 deletions(-) create mode 100644 libs/input/android/hardware/input/InputDeviceCountryCode.aidl (limited to 'libs/input/InputDevice.cpp') diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 3585392c2b..d51d6a722a 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -23,6 +23,8 @@ #include #include +#include "android/hardware/input/InputDeviceCountryCode.h" + namespace android { /* @@ -210,8 +212,10 @@ public: }; void initialize(int32_t id, int32_t generation, int32_t controllerNumber, - const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal, - bool hasMic); + const InputDeviceIdentifier& identifier, const std::string& alias, + bool isExternal, bool hasMic, + hardware::input::InputDeviceCountryCode countryCode = + hardware::input::InputDeviceCountryCode::INVALID); inline int32_t getId() const { return mId; } inline int32_t getControllerNumber() const { return mControllerNumber; } @@ -223,6 +227,7 @@ public: } inline bool isExternal() const { return mIsExternal; } inline bool hasMic() const { return mHasMic; } + inline hardware::input::InputDeviceCountryCode getCountryCode() const { return mCountryCode; } inline uint32_t getSources() const { return mSources; } const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; @@ -274,9 +279,11 @@ private: std::string mAlias; bool mIsExternal; bool mHasMic; + hardware::input::InputDeviceCountryCode mCountryCode; uint32_t mSources; int32_t mKeyboardType; std::shared_ptr mKeyCharacterMap; + bool mHasVibrator; bool mHasBattery; bool mHasButtonUnderPad; diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 5030d60da2..29e02cf73a 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -26,6 +26,7 @@ package { filegroup { name: "inputconstants_aidl", srcs: [ + "android/hardware/input/InputDeviceCountryCode.aidl", "android/os/IInputConstants.aidl", "android/os/InputEventInjectionResult.aidl", "android/os/InputEventInjectionSync.aidl", diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index a9089690b0..3fe03c7979 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -26,6 +26,7 @@ #include using android::base::StringPrintf; +using android::hardware::input::InputDeviceCountryCode; namespace android { @@ -177,6 +178,7 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mAlias(other.mAlias), mIsExternal(other.mIsExternal), mHasMic(other.mHasMic), + mCountryCode(other.mCountryCode), mSources(other.mSources), mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), @@ -192,8 +194,8 @@ InputDeviceInfo::~InputDeviceInfo() { } void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber, - const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal, - bool hasMic) { + const InputDeviceIdentifier& identifier, const std::string& alias, + bool isExternal, bool hasMic, InputDeviceCountryCode countryCode) { mId = id; mGeneration = generation; mControllerNumber = controllerNumber; @@ -201,6 +203,7 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mAlias = alias; mIsExternal = isExternal; mHasMic = hasMic; + mCountryCode = countryCode; mSources = 0; mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; mHasVibrator = false; diff --git a/libs/input/android/hardware/input/InputDeviceCountryCode.aidl b/libs/input/android/hardware/input/InputDeviceCountryCode.aidl new file mode 100644 index 0000000000..6bb1a60dda --- /dev/null +++ b/libs/input/android/hardware/input/InputDeviceCountryCode.aidl @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2022 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. + */ + +package android.hardware.input; + +/** + * Constant for HID country code declared by a HID device. These constants are declared as AIDL to + * be used by java and native input code. + * + * @hide + */ +@Backing(type="int") +enum InputDeviceCountryCode { + /** + * Used as default value where country code is not set in the device HID descriptor + */ + INVALID = -1, + + /** + * Used as default value when country code is not supported by the HID device. The HID + * descriptor sets "00" as the country code in this case. + */ + NOT_SUPPORTED = 0, + + /** + * Arabic + */ + ARABIC = 1, + + /** + * Belgian + */ + BELGIAN = 2, + + /** + * Canadian (Bilingual) + */ + CANADIAN_BILINGUAL = 3, + + /** + * Canadian (French) + */ + CANADIAN_FRENCH = 4, + + /** + * Czech Republic + */ + CZECH_REPUBLIC = 5, + + /** + * Danish + */ + DANISH = 6, + + /** + * Finnish + */ + FINNISH = 7, + + /** + * French + */ + FRENCH = 8, + + /** + * German + */ + GERMAN = 9, + + /** + * Greek + */ + GREEK = 10, + + /** + * Hebrew + */ + HEBREW = 11, + + /** + * Hungary + */ + HUNGARY = 12, + + /** + * International (ISO) + */ + INTERNATIONAL = 13, + + /** + * Italian + */ + ITALIAN = 14, + + /** + * Japan (Katakana) + */ + JAPAN = 15, + + /** + * Korean + */ + KOREAN = 16, + + /** + * Latin American + */ + LATIN_AMERICAN = 17, + + /** + * Netherlands (Dutch) + */ + DUTCH = 18, + + /** + * Norwegian + */ + NORWEGIAN = 19, + + /** + * Persian + */ + PERSIAN = 20, + + /** + * Poland + */ + POLAND = 21, + + /** + * Portuguese + */ + PORTUGUESE = 22, + + /** + * Russia + */ + RUSSIA = 23, + + /** + * Slovakia + */ + SLOVAKIA = 24, + + /** + * Spanish + */ + SPANISH = 25, + + /** + * Swedish + */ + SWEDISH = 26, + + /** + * Swiss (French) + */ + SWISS_FRENCH = 27, + + /** + * Swiss (German) + */ + SWISS_GERMAN = 28, + + /** + * Switzerland + */ + SWITZERLAND = 29, + + /** + * Taiwan + */ + TAIWAN = 30, + + /** + * Turkish_Q + */ + TURKISH_Q = 31, + + /** + * UK + */ + UK = 32, + + /** + * US + */ + US = 33, + + /** + * Yugoslavia + */ + YUGOSLAVIA = 34, + + /** + * Turkish_F + */ + TURKISH_F = 35, +} \ No newline at end of file diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 06a38c8f0f..336763c3c3 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -61,6 +61,7 @@ #define INDENT3 " " using android::base::StringPrintf; +using android::hardware::input::InputDeviceCountryCode; namespace android { @@ -301,6 +302,24 @@ static std::optional> getColorIndexArray( return colors; } +/** + * Read country code information exposed through the sysfs path. + */ +static InputDeviceCountryCode readCountryCodeLocked(const std::filesystem::path& sysfsRootPath) { + // Check the sysfs root path + int hidCountryCode = static_cast(InputDeviceCountryCode::INVALID); + std::string str; + if (base::ReadFileToString(sysfsRootPath / "country", &str)) { + hidCountryCode = std::stoi(str, nullptr, 16); + LOG_ALWAYS_FATAL_IF(hidCountryCode > 35 || hidCountryCode < 0, + "HID country code should be in range [0, 35]. Found country code " + "to be %d", + hidCountryCode); + } + + return static_cast(hidCountryCode); +} + /** * Read information about batteries exposed through the sysfs path. */ @@ -1238,6 +1257,15 @@ void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId, } } +InputDeviceCountryCode EventHub::getCountryCode(int32_t deviceId) const { + std::scoped_lock _l(mLock); + Device* device = getDeviceLocked(deviceId); + if (device == nullptr || !device->associatedDevice) { + return InputDeviceCountryCode::INVALID; + } + return device->associatedDevice->countryCode; +} + void EventHub::setExcludedDevices(const std::vector& devices) { std::scoped_lock _l(mLock); @@ -1384,6 +1412,7 @@ std::shared_ptr EventHub::obtainAssociatedDevi return std::make_shared( AssociatedDevice{.sysfsRootPath = path, + .countryCode = readCountryCodeLocked(path), .batteryInfos = readBatteryConfiguration(path), .lightInfos = readLightsConfiguration(path)}); } @@ -2553,6 +2582,9 @@ void EventHub::dump(std::string& dump) const { device->keyMap.keyLayoutFile.c_str()); dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n", device->keyMap.keyCharacterMapFile.c_str()); + dump += StringPrintf(INDENT3 "CountryCode: %d\n", + device->associatedDevice ? device->associatedDevice->countryCode + : InputDeviceCountryCode::INVALID); dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n", device->configurationFile.c_str()); dump += StringPrintf(INDENT3 "VideoDevice: %s\n", diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 5c9e63e80e..8eadcdcda8 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -35,6 +35,8 @@ #include "SwitchInputMapper.h" #include "VibratorInputMapper.h" +using android::hardware::input::InputDeviceCountryCode; + namespace android { InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation, @@ -240,6 +242,7 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config mSources = 0; mClasses = ftl::Flags(0); mControllerNumber = 0; + mCountryCode = InputDeviceCountryCode::INVALID; for_each_subdevice([this](InputDeviceContext& context) { mClasses |= context.getDeviceClasses(); @@ -251,6 +254,16 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config } mControllerNumber = controllerNumber; } + + InputDeviceCountryCode countryCode = context.getCountryCode(); + if (countryCode != InputDeviceCountryCode::INVALID) { + if (mCountryCode != InputDeviceCountryCode::INVALID && mCountryCode != countryCode) { + ALOGW("InputDevice::configure(): %s device contains multiple unique country " + "codes", + getName().c_str()); + } + mCountryCode = countryCode; + } }); mIsExternal = mClasses.test(InputDeviceClass::EXTERNAL); @@ -422,7 +435,7 @@ void InputDevice::updateExternalStylusState(const StylusState& state) { InputDeviceInfo InputDevice::getDeviceInfo() { InputDeviceInfo outDeviceInfo; outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal, - mHasMic); + mHasMic, mCountryCode); for_each_mapper( [&outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(&outDeviceInfo); }); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 8aec367795..dfb98f14c5 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -43,6 +43,7 @@ #include "TouchVideoDevice.h" #include "VibrationElement.h" +#include "android/hardware/input/InputDeviceCountryCode.h" struct inotify_event; @@ -301,9 +302,9 @@ public: int32_t deviceId, int32_t lightId) const = 0; virtual void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map intensities) = 0; - /* - * Query current input state. - */ + /* Query Country code associated with the input device. */ + virtual hardware::input::InputDeviceCountryCode getCountryCode(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; @@ -483,6 +484,8 @@ public: void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map intensities) override final; + hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const override final; + void setExcludedDevices(const std::vector& devices) override final; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final; @@ -544,7 +547,7 @@ private: struct AssociatedDevice { // The sysfs root path of the misc device. std::filesystem::path sysfsRootPath; - + hardware::input::InputDeviceCountryCode countryCode; std::unordered_map batteryInfos; std::unordered_map lightInfos; }; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 51872ac095..141464f6e4 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -158,6 +158,7 @@ private: int32_t mId; int32_t mGeneration; int32_t mControllerNumber; + hardware::input::InputDeviceCountryCode mCountryCode; InputDeviceIdentifier mIdentifier; std::string mAlias; ftl::Flags mClasses; @@ -311,6 +312,9 @@ public: } inline std::vector getVideoFrames() { return mEventHub->getVideoFrames(mId); } + inline hardware::input::InputDeviceCountryCode getCountryCode() const { + return mEventHub->getCountryCode(mId); + } inline int32_t getScanCodeState(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode); } diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 9a0c565de3..ae98415bf8 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -38,9 +38,12 @@ #include #include +#include "android/hardware/input/InputDeviceCountryCode.h" #include "input/DisplayViewport.h" #include "input/Input.h" +using android::hardware::input::InputDeviceCountryCode; + namespace android { using namespace ftl::flag_operators; @@ -455,6 +458,7 @@ class FakeEventHub : public EventHubInterface { BitArray mscBitmask; std::vector virtualKeys; bool enabled; + InputDeviceCountryCode countryCode; status_t enable() { enabled = true; @@ -584,6 +588,11 @@ public: device->keyCodeStates.replaceValueFor(keyCode, state); } + void setCountryCode(int32_t deviceId, InputDeviceCountryCode countryCode) { + Device* device = getDevice(deviceId); + device->countryCode = countryCode; + } + void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) { Device* device = getDevice(deviceId); device->scanCodeStates.replaceValueFor(scanCode, state); @@ -845,6 +854,14 @@ private: return AKEY_STATE_UNKNOWN; } + InputDeviceCountryCode getCountryCode(int32_t deviceId) const override { + Device* device = getDevice(deviceId); + if (device) { + return device->countryCode; + } + return InputDeviceCountryCode::INVALID; + } + int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override { Device* device = getDevice(deviceId); if (device) { @@ -2685,6 +2702,17 @@ TEST_F(InputDeviceTest, ImmutableProperties) { ASSERT_EQ(ftl::Flags(0), mDevice->getClasses()); } +TEST_F(InputDeviceTest, CountryCodeCorrectlyMapped) { + mFakeEventHub->setCountryCode(EVENTHUB_ID, InputDeviceCountryCode::INTERNATIONAL); + + // Configuration + mDevice->addMapper(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD); + InputReaderConfiguration config; + mDevice->configure(ARBITRARY_TIME, &config, 0); + + ASSERT_EQ(InputDeviceCountryCode::INTERNATIONAL, mDevice->getDeviceInfo().getCountryCode()); +} + TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) { ASSERT_EQ(mDevice->isEnabled(), false); } -- cgit v1.2.3-59-g8ed1b From 167c270ea82781d0a003c05292ff623fcb5f8243 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Wed, 14 Sep 2022 00:37:24 +0000 Subject: Determine whether an input device supports USI using IDC files It is necessary to identify a USI device so that additional logic can be applied to the battery information that is exposed via USI. Bug: 243005009 Test: manual, check dumpsys output Change-Id: I697008e6600ef16b7ecde85c99732759747b8a9b --- include/input/InputDevice.h | 5 +++++ libs/input/InputDevice.cpp | 2 ++ services/inputflinger/reader/mapper/TouchInputMapper.cpp | 6 ++++++ services/inputflinger/reader/mapper/TouchInputMapper.h | 3 +++ 4 files changed, 16 insertions(+) (limited to 'libs/input/InputDevice.cpp') diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 0026e82caa..f4a15238cf 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -280,6 +280,9 @@ public: std::vector getLights(); + inline void setSupportsUsi(bool supportsUsi) { mSupportsUsi = supportsUsi; } + inline bool supportsUsi() const { return mSupportsUsi; } + private: int32_t mId; int32_t mGeneration; @@ -292,6 +295,8 @@ private: uint32_t mSources; int32_t mKeyboardType; std::shared_ptr mKeyCharacterMap; + // Whether this device supports the Universal Stylus Initiative (USI) protocol for styluses. + bool mSupportsUsi; bool mHasVibrator; bool mHasBattery; diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 3fe03c7979..4751a7de8b 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -182,6 +182,7 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mSources(other.mSources), mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), + mSupportsUsi(other.mSupportsUsi), mHasVibrator(other.mHasVibrator), mHasBattery(other.mHasBattery), mHasButtonUnderPad(other.mHasButtonUnderPad), @@ -210,6 +211,7 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mHasBattery = false; mHasButtonUnderPad = false; mHasSensor = false; + mSupportsUsi = false; mMotionRanges.clear(); mSensors.clear(); mLights.clear(); diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index c2454ac6d4..18a73eadfb 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -256,6 +256,7 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { y.resolution); } info->setButtonUnderPad(mParameters.hasButtonUnderPad); + info->setSupportsUsi(mParameters.supportsUsi); } void TouchInputMapper::dump(std::string& dump) { @@ -505,6 +506,10 @@ void TouchInputMapper::configureParameters() { // up in your pocket but you can enable it using the input device configuration. mParameters.wake = getDeviceContext().isExternal(); getDeviceContext().getConfiguration().tryGetProperty("touch.wake", mParameters.wake); + + mParameters.supportsUsi = false; + getDeviceContext().getConfiguration().tryGetProperty("touch.supportsUsi", + mParameters.supportsUsi); } void TouchInputMapper::dumpParameters(std::string& dump) { @@ -521,6 +526,7 @@ void TouchInputMapper::dumpParameters(std::string& dump) { mParameters.uniqueDisplayId.c_str()); dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); dump += INDENT4 "Orientation: " + ftl::enum_string(mParameters.orientation) + "\n"; + dump += StringPrintf(INDENT4 "SupportsUsi: %s\n", toString(mParameters.supportsUsi)); } void TouchInputMapper::configureRawPointerAxes() { diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index 50f30c824e..7b0327e913 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -232,6 +232,9 @@ protected: GestureMode gestureMode; bool wake; + + // Whether the device supports the Universal Stylus Initiative (USI) protocol for styluses. + bool supportsUsi; } mParameters; // Immutable calibration parameters in parsed form. -- cgit v1.2.3-59-g8ed1b From fecb60640999c4758a8967e7d7960d4530198d17 Mon Sep 17 00:00:00 2001 From: Zixuan Qu Date: Sat, 12 Nov 2022 04:44:31 +0000 Subject: Gets keyboard layout info from user space when available. The layout info consists of a BCP 47 conformant language tag and a layout type such as "qwerty" or "azerty". They will be used to initialize the input device. This is currently used by uinput virtual keyboard to pass in layout information. Bug: 237537306 Test: atest inputflinger_tests Change-Id: Icfc30f1afb0f88dd704d1d598d62a300a032b0f5 --- include/input/InputDevice.h | 16 ++++++++++++++++ libs/input/InputDevice.cpp | 5 +++++ services/inputflinger/include/InputReaderBase.h | 9 ++++++++- services/inputflinger/reader/InputDevice.cpp | 10 ---------- services/inputflinger/reader/Macros.h | 12 ++++++++++++ services/inputflinger/reader/include/InputDevice.h | 2 ++ .../reader/mapper/KeyboardInputMapper.cpp | 16 ++++++++++++++++ .../inputflinger/reader/mapper/KeyboardInputMapper.h | 1 + .../inputflinger/tests/FakeInputReaderPolicy.cpp | 5 +++++ services/inputflinger/tests/FakeInputReaderPolicy.h | 2 ++ services/inputflinger/tests/InputReader_test.cpp | 20 +++++++++++++++++++- 11 files changed, 86 insertions(+), 12 deletions(-) (limited to 'libs/input/InputDevice.cpp') diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index e911734407..5fa9fda64b 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -205,6 +205,16 @@ struct InputDeviceBatteryInfo { int32_t id; }; +struct KeyboardLayoutInfo { + explicit KeyboardLayoutInfo(std::string languageTag, std::string layoutType) + : languageTag(languageTag), layoutType(layoutType) {} + + // A BCP 47 conformant language tag such as "en-US". + std::string languageTag; + // The layout type such as QWERTY or AZERTY. + std::string layoutType; +}; + /* * Describes the characteristics and capabilities of an input device. */ @@ -256,6 +266,11 @@ public: void setKeyboardType(int32_t keyboardType); inline int32_t getKeyboardType() const { return mKeyboardType; } + void setKeyboardLayoutInfo(KeyboardLayoutInfo keyboardLayoutInfo); + inline const std::optional& getKeyboardLayoutInfo() const { + return mKeyboardLayoutInfo; + } + inline void setKeyCharacterMap(const std::shared_ptr value) { mKeyCharacterMap = value; } @@ -296,6 +311,7 @@ private: bool mIsExternal; bool mHasMic; hardware::input::InputDeviceCountryCode mCountryCode; + std::optional mKeyboardLayoutInfo; uint32_t mSources; int32_t mKeyboardType; std::shared_ptr mKeyCharacterMap; diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 4751a7de8b..fb6c590b6e 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -179,6 +179,7 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mIsExternal(other.mIsExternal), mHasMic(other.mHasMic), mCountryCode(other.mCountryCode), + mKeyboardLayoutInfo(other.mKeyboardLayoutInfo), mSources(other.mSources), mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), @@ -270,6 +271,10 @@ void InputDeviceInfo::setKeyboardType(int32_t keyboardType) { mKeyboardType = std::max(mKeyboardType, keyboardType); } +void InputDeviceInfo::setKeyboardLayoutInfo(KeyboardLayoutInfo layoutInfo) { + mKeyboardLayoutInfo = std::move(layoutInfo); +} + std::vector InputDeviceInfo::getSensors() { std::vector infos; infos.reserve(mSensors.size()); diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 3e4db43cbe..d2c940ff47 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -194,6 +194,9 @@ struct InputReaderConfiguration { // The device type has been updated. CHANGE_DEVICE_TYPE = 1 << 10, + // The keyboard layout association has changed. + CHANGE_KEYBOARD_LAYOUT_ASSOCIATION = 1 << 11, + // All devices must be reopened. CHANGE_MUST_REOPEN = 1 << 31, }; @@ -211,7 +214,7 @@ struct InputReaderConfiguration { // Used to determine which DisplayViewport should be tied to which InputDevice. std::unordered_map portAssociations; - // The associations between input device names and display unique ids. + // The associations between input device physical port locations and display unique ids. // Used to determine which DisplayViewport should be tied to which InputDevice. std::unordered_map uniqueIdAssociations; @@ -219,6 +222,10 @@ struct InputReaderConfiguration { // This is used to determine which device type and source should be tied to which InputDevice. std::unordered_map deviceTypeAssociations; + // The map from the input device physical port location to the input device layout info. + // Can be used to determine the layout of the keyboard device. + std::unordered_map keyboardLayoutAssociations; + // The suggested display ID to show the cursor. int32_t defaultPointerDisplayId; diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 6dfe5f52fa..13f40ee8e4 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -56,16 +56,6 @@ InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t genera InputDevice::~InputDevice() {} -template -std::optional getValueByKey(const std::unordered_map& map, K key) { - auto it = map.find(key); - std::optional value = std::nullopt; - if (it != map.end()) { - value = it->second; - } - return value; -} - bool InputDevice::isEnabled() { if (!hasEventHubDevices()) { return false; diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h index e107d882b7..d2a7ced864 100644 --- a/services/inputflinger/reader/Macros.h +++ b/services/inputflinger/reader/Macros.h @@ -22,6 +22,8 @@ #include #include +#include + namespace android { /** * Log debug messages for each raw event received from the EventHub. @@ -113,4 +115,14 @@ static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { return (sources & sourceMask & ~AINPUT_SOURCE_CLASS_MASK) != 0; } +template +static inline std::optional getValueByKey(const std::unordered_map& map, K key) { + auto it = map.find(key); + std::optional value = std::nullopt; + if (it != map.end()) { + value = it->second; + } + return value; +} + } // namespace android diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index af59fe2aca..6179f05f6d 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -54,6 +54,7 @@ public: inline std::optional getBluetoothAddress() const { return mIdentifier.bluetoothAddress; } + inline const std::string getLocation() const { return mIdentifier.location; } inline ftl::Flags getClasses() const { return mClasses; } inline uint32_t getSources() const { return mSources; } inline bool hasEventHubDevices() const { return !mDevices.empty(); } @@ -405,6 +406,7 @@ public: inline const std::string getName() { return mDevice.getName(); } inline const std::string getDescriptor() { return mDevice.getDescriptor(); } + inline const std::string getLocation() { return mDevice.getLocation(); } inline bool isExternal() { return mDevice.isExternal(); } inline std::optional getAssociatedDisplayPort() const { return mDevice.getAssociatedDisplayPort(); diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 44f0dfe3b6..6f01449083 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -120,6 +120,10 @@ void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { info->setKeyboardType(mKeyboardType); info->setKeyCharacterMap(getDeviceContext().getKeyCharacterMap()); + + if (mKeyboardLayoutInfo) { + info->setKeyboardLayoutInfo(*mKeyboardLayoutInfo); + } } void KeyboardInputMapper::dump(std::string& dump) { @@ -129,6 +133,12 @@ void KeyboardInputMapper::dump(std::string& dump) { dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation()); dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size()); dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState); + dump += INDENT3 "KeyboardLayoutInfo: "; + if (mKeyboardLayoutInfo) { + dump += mKeyboardLayoutInfo->languageTag + ", " + mKeyboardLayoutInfo->layoutType + "\n"; + } else { + dump += "\n"; + } } std::optional KeyboardInputMapper::findViewport( @@ -158,6 +168,12 @@ std::list KeyboardInputMapper::configure(nsecs_t when, if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { mViewport = findViewport(config); } + + if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUT_ASSOCIATION)) { + mKeyboardLayoutInfo = + getValueByKey(config->keyboardLayoutAssociations, getDeviceContext().getLocation()); + } + return out; } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index 0526fd89de..da5b8ee4f3 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -58,6 +58,7 @@ private: uint32_t mSource{}; int32_t mKeyboardType{}; + std::optional mKeyboardLayoutInfo; std::vector mKeyDowns{}; // keys that are down int32_t mMetaState{}; diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp index dc7e581abd..f7553563cf 100644 --- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp +++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp @@ -136,6 +136,11 @@ void FakeInputReaderPolicy::addInputUniqueIdAssociation(const std::string& input mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId}); } +void FakeInputReaderPolicy::addKeyboardLayoutAssociation(const std::string& inputUniqueId, + const KeyboardLayoutInfo& layoutInfo) { + mConfig.keyboardLayoutAssociations.insert({inputUniqueId, layoutInfo}); +} + void FakeInputReaderPolicy::addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); } diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h index faa9c01a98..862ff0b21a 100644 --- a/services/inputflinger/tests/FakeInputReaderPolicy.h +++ b/services/inputflinger/tests/FakeInputReaderPolicy.h @@ -58,6 +58,8 @@ public: void addDeviceTypeAssociation(const std::string& inputPort, const std::string& type); void addInputUniqueIdAssociation(const std::string& inputUniqueId, const std::string& displayUniqueId); + void addKeyboardLayoutAssociation(const std::string& inputUniqueId, + const KeyboardLayoutInfo& layoutInfo); void addDisabledDevice(int32_t deviceId); void removeDisabledDevice(int32_t deviceId); void setPointerController(std::shared_ptr controller); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 3516092cef..5b0185fc8e 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -2763,7 +2763,7 @@ TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) { class KeyboardInputMapperTest : public InputMapperTest { protected: const std::string UNIQUE_ID = "local:0"; - + const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty"); void prepareDisplay(ui::Rotation orientation); void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode, @@ -3582,6 +3582,24 @@ TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) { ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags); } +TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) { + mDevice->addMapper(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + std::list unused = + mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0); + + mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO); + + unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), + InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUT_ASSOCIATION); + + InputDeviceInfo deviceInfo = mDevice->getDeviceInfo(); + ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag, + deviceInfo.getKeyboardLayoutInfo()->languageTag); + ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType, + deviceInfo.getKeyboardLayoutInfo()->layoutType); +} + // --- KeyboardInputMapperTest_ExternalDevice --- class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest { -- cgit v1.2.3-59-g8ed1b From 7fb411367ff01ef737ad6dff2dcd68d60a06a09e Mon Sep 17 00:00:00 2001 From: Vaibhav Devmurari Date: Mon, 2 Jan 2023 13:30:26 +0000 Subject: Convert country code to Layoutinfo (Language tag + Layout type) Instead of passing country code to InputDevice.java, convert it to Language tag and Layout type on native side and pass that forward instead. We can later add support for HID language tag, that would give us better layout information than country code. This HID language tag is for Keyboard devices so, we set this country code derived language tag also for Keyboards only, even though country code could be specified for all types of devices. Moreover, we are using language tag and layout type for setting layout related info for Virtual keyboard devices too, making using country code redundant. Test: atest inputflinger_tests Bug: 259530132 Change-Id: I8eca5537a5bb44d0b8b056947cc317ac82a0901f --- include/input/InputDevice.h | 7 +- libs/input/Android.bp | 1 - libs/input/InputDevice.cpp | 5 +- .../hardware/input/InputDeviceCountryCode.aidl | 212 --------------------- services/inputflinger/reader/EventHub.cpp | 75 ++++++-- services/inputflinger/reader/InputDevice.cpp | 15 +- services/inputflinger/reader/include/EventHub.h | 18 +- services/inputflinger/reader/include/InputDevice.h | 7 +- .../reader/mapper/KeyboardInputMapper.cpp | 6 + services/inputflinger/tests/FakeEventHub.cpp | 8 +- services/inputflinger/tests/FakeEventHub.h | 10 +- services/inputflinger/tests/InputReader_test.cpp | 28 +-- .../inputflinger/tests/fuzzers/MapperHelpers.h | 47 +---- 13 files changed, 109 insertions(+), 330 deletions(-) delete mode 100644 libs/input/android/hardware/input/InputDeviceCountryCode.aidl (limited to 'libs/input/InputDevice.cpp') diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 5fa9fda64b..09933d32b1 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -24,7 +24,6 @@ #include #include -#include "android/hardware/input/InputDeviceCountryCode.h" namespace android { @@ -236,9 +235,7 @@ public: void initialize(int32_t id, int32_t generation, int32_t controllerNumber, const InputDeviceIdentifier& identifier, const std::string& alias, - bool isExternal, bool hasMic, - hardware::input::InputDeviceCountryCode countryCode = - hardware::input::InputDeviceCountryCode::INVALID); + bool isExternal, bool hasMic); inline int32_t getId() const { return mId; } inline int32_t getControllerNumber() const { return mControllerNumber; } @@ -250,7 +247,6 @@ public: } inline bool isExternal() const { return mIsExternal; } inline bool hasMic() const { return mHasMic; } - inline hardware::input::InputDeviceCountryCode getCountryCode() const { return mCountryCode; } inline uint32_t getSources() const { return mSources; } const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; @@ -310,7 +306,6 @@ private: std::string mAlias; bool mIsExternal; bool mHasMic; - hardware::input::InputDeviceCountryCode mCountryCode; std::optional mKeyboardLayoutInfo; uint32_t mSources; int32_t mKeyboardType; diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 8ddd18d84a..8f41cc1872 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -26,7 +26,6 @@ package { filegroup { name: "inputconstants_aidl", srcs: [ - "android/hardware/input/InputDeviceCountryCode.aidl", "android/os/IInputConstants.aidl", "android/os/InputEventInjectionResult.aidl", "android/os/InputEventInjectionSync.aidl", diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index fb6c590b6e..87333f2c76 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -26,7 +26,6 @@ #include using android::base::StringPrintf; -using android::hardware::input::InputDeviceCountryCode; namespace android { @@ -178,7 +177,6 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mAlias(other.mAlias), mIsExternal(other.mIsExternal), mHasMic(other.mHasMic), - mCountryCode(other.mCountryCode), mKeyboardLayoutInfo(other.mKeyboardLayoutInfo), mSources(other.mSources), mKeyboardType(other.mKeyboardType), @@ -197,7 +195,7 @@ InputDeviceInfo::~InputDeviceInfo() { void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber, const InputDeviceIdentifier& identifier, const std::string& alias, - bool isExternal, bool hasMic, InputDeviceCountryCode countryCode) { + bool isExternal, bool hasMic) { mId = id; mGeneration = generation; mControllerNumber = controllerNumber; @@ -205,7 +203,6 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mAlias = alias; mIsExternal = isExternal; mHasMic = hasMic; - mCountryCode = countryCode; mSources = 0; mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; mHasVibrator = false; diff --git a/libs/input/android/hardware/input/InputDeviceCountryCode.aidl b/libs/input/android/hardware/input/InputDeviceCountryCode.aidl deleted file mode 100644 index 6bb1a60dda..0000000000 --- a/libs/input/android/hardware/input/InputDeviceCountryCode.aidl +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2022 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. - */ - -package android.hardware.input; - -/** - * Constant for HID country code declared by a HID device. These constants are declared as AIDL to - * be used by java and native input code. - * - * @hide - */ -@Backing(type="int") -enum InputDeviceCountryCode { - /** - * Used as default value where country code is not set in the device HID descriptor - */ - INVALID = -1, - - /** - * Used as default value when country code is not supported by the HID device. The HID - * descriptor sets "00" as the country code in this case. - */ - NOT_SUPPORTED = 0, - - /** - * Arabic - */ - ARABIC = 1, - - /** - * Belgian - */ - BELGIAN = 2, - - /** - * Canadian (Bilingual) - */ - CANADIAN_BILINGUAL = 3, - - /** - * Canadian (French) - */ - CANADIAN_FRENCH = 4, - - /** - * Czech Republic - */ - CZECH_REPUBLIC = 5, - - /** - * Danish - */ - DANISH = 6, - - /** - * Finnish - */ - FINNISH = 7, - - /** - * French - */ - FRENCH = 8, - - /** - * German - */ - GERMAN = 9, - - /** - * Greek - */ - GREEK = 10, - - /** - * Hebrew - */ - HEBREW = 11, - - /** - * Hungary - */ - HUNGARY = 12, - - /** - * International (ISO) - */ - INTERNATIONAL = 13, - - /** - * Italian - */ - ITALIAN = 14, - - /** - * Japan (Katakana) - */ - JAPAN = 15, - - /** - * Korean - */ - KOREAN = 16, - - /** - * Latin American - */ - LATIN_AMERICAN = 17, - - /** - * Netherlands (Dutch) - */ - DUTCH = 18, - - /** - * Norwegian - */ - NORWEGIAN = 19, - - /** - * Persian - */ - PERSIAN = 20, - - /** - * Poland - */ - POLAND = 21, - - /** - * Portuguese - */ - PORTUGUESE = 22, - - /** - * Russia - */ - RUSSIA = 23, - - /** - * Slovakia - */ - SLOVAKIA = 24, - - /** - * Spanish - */ - SPANISH = 25, - - /** - * Swedish - */ - SWEDISH = 26, - - /** - * Swiss (French) - */ - SWISS_FRENCH = 27, - - /** - * Swiss (German) - */ - SWISS_GERMAN = 28, - - /** - * Switzerland - */ - SWITZERLAND = 29, - - /** - * Taiwan - */ - TAIWAN = 30, - - /** - * Turkish_Q - */ - TURKISH_Q = 31, - - /** - * UK - */ - UK = 32, - - /** - * US - */ - US = 33, - - /** - * Yugoslavia - */ - YUGOSLAVIA = 34, - - /** - * Turkish_F - */ - TURKISH_F = 35, -} \ No newline at end of file diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index e9fa599b33..b214750443 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -62,7 +62,6 @@ #define INDENT3 " " using android::base::StringPrintf; -using android::hardware::input::InputDeviceCountryCode; namespace android { @@ -135,6 +134,46 @@ const std::unordered_map LIGHT_COLORS = {{"red", LightC {"green", LightColor::GREEN}, {"blue", LightColor::BLUE}}; +// Mapping for country code to Layout info. +// See bCountryCode in 6.2.1 of https://usb.org/sites/default/files/hid1_11.pdf. +const std::unordered_map LAYOUT_INFOS = + {{0, RawLayoutInfo{.languageTag = "", .layoutType = ""}}, // NOT_SUPPORTED + {1, RawLayoutInfo{.languageTag = "ar-Arab", .layoutType = ""}}, // ARABIC + {2, RawLayoutInfo{.languageTag = "fr-BE", .layoutType = ""}}, // BELGIAN + {3, RawLayoutInfo{.languageTag = "fr-CA", .layoutType = ""}}, // CANADIAN_BILINGUAL + {4, RawLayoutInfo{.languageTag = "fr-CA", .layoutType = ""}}, // CANADIAN_FRENCH + {5, RawLayoutInfo{.languageTag = "cs", .layoutType = ""}}, // CZECH_REPUBLIC + {6, RawLayoutInfo{.languageTag = "da", .layoutType = ""}}, // DANISH + {7, RawLayoutInfo{.languageTag = "fi", .layoutType = ""}}, // FINNISH + {8, RawLayoutInfo{.languageTag = "fr-FR", .layoutType = ""}}, // FRENCH + {9, RawLayoutInfo{.languageTag = "de", .layoutType = ""}}, // GERMAN + {10, RawLayoutInfo{.languageTag = "el", .layoutType = ""}}, // GREEK + {11, RawLayoutInfo{.languageTag = "iw", .layoutType = ""}}, // HEBREW + {12, RawLayoutInfo{.languageTag = "hu", .layoutType = ""}}, // HUNGARY + {13, RawLayoutInfo{.languageTag = "en", .layoutType = "extended"}}, // INTERNATIONAL (ISO) + {14, RawLayoutInfo{.languageTag = "it", .layoutType = ""}}, // ITALIAN + {15, RawLayoutInfo{.languageTag = "ja", .layoutType = ""}}, // JAPAN + {16, RawLayoutInfo{.languageTag = "ko", .layoutType = ""}}, // KOREAN + {17, RawLayoutInfo{.languageTag = "es-419", .layoutType = ""}}, // LATIN_AMERICA + {18, RawLayoutInfo{.languageTag = "nl", .layoutType = ""}}, // DUTCH + {19, RawLayoutInfo{.languageTag = "nb", .layoutType = ""}}, // NORWEGIAN + {20, RawLayoutInfo{.languageTag = "fa", .layoutType = ""}}, // PERSIAN + {21, RawLayoutInfo{.languageTag = "pl", .layoutType = ""}}, // POLAND + {22, RawLayoutInfo{.languageTag = "pt", .layoutType = ""}}, // PORTUGUESE + {23, RawLayoutInfo{.languageTag = "ru", .layoutType = ""}}, // RUSSIA + {24, RawLayoutInfo{.languageTag = "sk", .layoutType = ""}}, // SLOVAKIA + {25, RawLayoutInfo{.languageTag = "es-ES", .layoutType = ""}}, // SPANISH + {26, RawLayoutInfo{.languageTag = "sv", .layoutType = ""}}, // SWEDISH + {27, RawLayoutInfo{.languageTag = "fr-CH", .layoutType = ""}}, // SWISS_FRENCH + {28, RawLayoutInfo{.languageTag = "de-CH", .layoutType = ""}}, // SWISS_GERMAN + {29, RawLayoutInfo{.languageTag = "de-CH", .layoutType = ""}}, // SWITZERLAND + {30, RawLayoutInfo{.languageTag = "zh-TW", .layoutType = ""}}, // TAIWAN + {31, RawLayoutInfo{.languageTag = "tr", .layoutType = "turkish_q"}}, // TURKISH_Q + {32, RawLayoutInfo{.languageTag = "en-GB", .layoutType = ""}}, // UK + {33, RawLayoutInfo{.languageTag = "en-US", .layoutType = ""}}, // US + {34, RawLayoutInfo{.languageTag = "", .layoutType = ""}}, // YUGOSLAVIA + {35, RawLayoutInfo{.languageTag = "tr", .layoutType = "turkish_f"}}}; // TURKISH_F + static std::string sha1(const std::string& in) { SHA_CTX ctx; SHA1_Init(&ctx); @@ -311,22 +350,27 @@ static std::optional> getColorIndexArray( } /** - * Read country code information exposed through the sysfs path. + * Read country code information exposed through the sysfs path and convert it to Layout info. */ -static InputDeviceCountryCode readCountryCodeLocked(const std::filesystem::path& sysfsRootPath) { +static std::optional readLayoutConfiguration( + const std::filesystem::path& sysfsRootPath) { // Check the sysfs root path - int hidCountryCode = static_cast(InputDeviceCountryCode::INVALID); + int32_t hidCountryCode = -1; std::string str; if (base::ReadFileToString(sysfsRootPath / "country", &str)) { hidCountryCode = std::stoi(str, nullptr, 16); + // Update this condition if new supported country codes are added to HID spec. if (hidCountryCode > 35 || hidCountryCode < 0) { ALOGE("HID country code should be in range [0, 35], but for sysfs path %s it was %d", sysfsRootPath.c_str(), hidCountryCode); - return InputDeviceCountryCode::INVALID; } } + const auto it = LAYOUT_INFOS.find(hidCountryCode); + if (it != LAYOUT_INFOS.end()) { + return it->second; + } - return static_cast(hidCountryCode); + return std::nullopt; } /** @@ -1299,13 +1343,13 @@ void EventHub::setLightIntensities(int32_t deviceId, int32_t lightId, } } -InputDeviceCountryCode EventHub::getCountryCode(int32_t deviceId) const { +std::optional EventHub::getRawLayoutInfo(int32_t deviceId) const { std::scoped_lock _l(mLock); Device* device = getDeviceLocked(deviceId); if (device == nullptr || !device->associatedDevice) { - return InputDeviceCountryCode::INVALID; + return std::nullopt; } - return device->associatedDevice->countryCode; + return device->associatedDevice->layoutInfo; } void EventHub::setExcludedDevices(const std::vector& devices) { @@ -1449,9 +1493,9 @@ std::shared_ptr EventHub::obtainAssociatedDevi std::shared_ptr associatedDevice = std::make_shared( AssociatedDevice{.sysfsRootPath = path, - .countryCode = readCountryCodeLocked(path), .batteryInfos = readBatteryConfiguration(path), - .lightInfos = readLightsConfiguration(path)}); + .lightInfos = readLightsConfiguration(path), + .layoutInfo = readLayoutConfiguration(path)}); bool associatedDeviceChanged = false; for (const auto& [id, dev] : mDevices) { @@ -2686,9 +2730,12 @@ void EventHub::dump(std::string& dump) const { device->keyMap.keyLayoutFile.c_str()); dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n", device->keyMap.keyCharacterMapFile.c_str()); - dump += StringPrintf(INDENT3 "CountryCode: %d\n", - device->associatedDevice ? device->associatedDevice->countryCode - : InputDeviceCountryCode::INVALID); + if (device->associatedDevice && device->associatedDevice->layoutInfo) { + dump += StringPrintf(INDENT3 "LanguageTag: %s\n", + device->associatedDevice->layoutInfo->languageTag.c_str()); + dump += StringPrintf(INDENT3 "LayoutType: %s\n", + device->associatedDevice->layoutInfo->layoutType.c_str()); + } dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n", device->configurationFile.c_str()); dump += StringPrintf(INDENT3 "VideoDevice: %s\n", diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 13f40ee8e4..6e78e82c7e 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -37,8 +37,6 @@ #include "TouchpadInputMapper.h" #include "VibratorInputMapper.h" -using android::hardware::input::InputDeviceCountryCode; - namespace android { InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation, @@ -256,7 +254,6 @@ std::list InputDevice::configure(nsecs_t when, const InputReaderConf mSources = 0; mClasses = ftl::Flags(0); mControllerNumber = 0; - mCountryCode = InputDeviceCountryCode::INVALID; for_each_subdevice([this](InputDeviceContext& context) { mClasses |= context.getDeviceClasses(); @@ -268,16 +265,6 @@ std::list InputDevice::configure(nsecs_t when, const InputReaderConf } mControllerNumber = controllerNumber; } - - InputDeviceCountryCode countryCode = context.getCountryCode(); - if (countryCode != InputDeviceCountryCode::INVALID) { - if (mCountryCode != InputDeviceCountryCode::INVALID && mCountryCode != countryCode) { - ALOGW("InputDevice::configure(): %s device contains multiple unique country " - "codes", - getName().c_str()); - } - mCountryCode = countryCode; - } }); mIsExternal = mClasses.test(InputDeviceClass::EXTERNAL); @@ -465,7 +452,7 @@ std::list InputDevice::updateExternalStylusState(const StylusState& InputDeviceInfo InputDevice::getDeviceInfo() { InputDeviceInfo outDeviceInfo; outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal, - mHasMic, mCountryCode); + mHasMic); for_each_mapper( [&outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(&outDeviceInfo); }); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 8a844b2088..a3ecf418bb 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -42,7 +42,6 @@ #include "TouchVideoDevice.h" #include "VibrationElement.h" -#include "android/hardware/input/InputDeviceCountryCode.h" struct inotify_event; @@ -207,6 +206,15 @@ struct RawBatteryInfo { 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. @@ -308,8 +316,8 @@ public: int32_t deviceId, int32_t lightId) const = 0; virtual void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map intensities) = 0; - /* Query Country code associated with the input device. */ - virtual hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const = 0; + /* Query Layout info associated with the input device. */ + virtual std::optional 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; @@ -493,7 +501,7 @@ public: void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map intensities) override final; - hardware::input::InputDeviceCountryCode getCountryCode(int32_t deviceId) const override final; + std::optional getRawLayoutInfo(int32_t deviceId) const override final; void setExcludedDevices(const std::vector& devices) override final; @@ -556,9 +564,9 @@ private: struct AssociatedDevice { // The sysfs root path of the misc device. std::filesystem::path sysfsRootPath; - hardware::input::InputDeviceCountryCode countryCode; std::unordered_map batteryInfos; std::unordered_map lightInfos; + std::optional layoutInfo; bool operator==(const AssociatedDevice&) const = default; bool operator!=(const AssociatedDevice&) const = default; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index b173618d87..7867029ab7 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -167,7 +167,6 @@ private: int32_t mId; int32_t mGeneration; int32_t mControllerNumber; - hardware::input::InputDeviceCountryCode mCountryCode; InputDeviceIdentifier mIdentifier; std::string mAlias; ftl::Flags mClasses; @@ -326,9 +325,6 @@ public: } inline std::vector getVideoFrames() { return mEventHub->getVideoFrames(mId); } - inline hardware::input::InputDeviceCountryCode getCountryCode() const { - return mEventHub->getCountryCode(mId); - } inline int32_t getScanCodeState(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode); } @@ -361,6 +357,9 @@ public: inline bool setKeyboardLayoutOverlay(std::shared_ptr map) { return mEventHub->setKeyboardLayoutOverlay(mId, map); } + inline const std::optional getRawLayoutInfo() { + return mEventHub->getRawLayoutInfo(mId); + } inline void vibrate(const VibrationElement& element) { return mEventHub->vibrate(mId, element); } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 6f01449083..d147d60f4e 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -123,6 +123,12 @@ void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { if (mKeyboardLayoutInfo) { info->setKeyboardLayoutInfo(*mKeyboardLayoutInfo); + } else { + std::optional layoutInfo = getDeviceContext().getRawLayoutInfo(); + if (layoutInfo) { + info->setKeyboardLayoutInfo( + KeyboardLayoutInfo(layoutInfo->languageTag, layoutInfo->layoutType)); + } } } diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index 289a7809cc..6ac0bfb541 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -120,8 +120,8 @@ void FakeEventHub::setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t st getDevice(deviceId)->keyCodeStates.replaceValueFor(keyCode, state); } -void FakeEventHub::setCountryCode(int32_t deviceId, InputDeviceCountryCode countryCode) { - getDevice(deviceId)->countryCode = countryCode; +void FakeEventHub::setRawLayoutInfo(int32_t deviceId, RawLayoutInfo info) { + getDevice(deviceId)->layoutInfo = info; } void FakeEventHub::setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) { @@ -389,9 +389,9 @@ int32_t FakeEventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const return AKEY_STATE_UNKNOWN; } -InputDeviceCountryCode FakeEventHub::getCountryCode(int32_t deviceId) const { +std::optional FakeEventHub::getRawLayoutInfo(int32_t deviceId) const { Device* device = getDevice(deviceId); - return device ? device->countryCode : InputDeviceCountryCode::INVALID; + return device ? device->layoutInfo : std::nullopt; } int32_t FakeEventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const { diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index fb3c8596c7..72f8ac03a5 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -30,10 +30,6 @@ #include #include -#include "android/hardware/input/InputDeviceCountryCode.h" - -using android::hardware::input::InputDeviceCountryCode; - namespace android { class FakeEventHub : public EventHubInterface { @@ -67,7 +63,7 @@ class FakeEventHub : public EventHubInterface { BitArray mscBitmask; std::vector virtualKeys; bool enabled; - InputDeviceCountryCode countryCode; + std::optional layoutInfo; status_t enable() { enabled = true; @@ -124,7 +120,7 @@ public: void addRelativeAxis(int32_t deviceId, int32_t axis); void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value); - void setCountryCode(int32_t deviceId, InputDeviceCountryCode countryCode); + void setRawLayoutInfo(int32_t deviceId, RawLayoutInfo info); void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state); void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state); @@ -180,7 +176,7 @@ private: std::vector getEvents(int) override; std::vector getVideoFrames(int32_t deviceId) override; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override; - InputDeviceCountryCode getCountryCode(int32_t deviceId) const override; + std::optional getRawLayoutInfo(int32_t deviceId) const override; int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override; int32_t getSwitchState(int32_t deviceId, int32_t sw) const override; status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const override; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 96d27b8f11..a46463924f 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -48,12 +48,9 @@ #include "InputMapperTest.h" #include "InstrumentedInputReader.h" #include "TestConstants.h" -#include "android/hardware/input/InputDeviceCountryCode.h" #include "input/DisplayViewport.h" #include "input/Input.h" -using android::hardware::input::InputDeviceCountryCode; - namespace android { using namespace ftl::flag_operators; @@ -2240,17 +2237,6 @@ TEST_F(InputDeviceTest, ImmutableProperties) { ASSERT_EQ(ftl::Flags(0), mDevice->getClasses()); } -TEST_F(InputDeviceTest, CountryCodeCorrectlyMapped) { - mFakeEventHub->setCountryCode(EVENTHUB_ID, InputDeviceCountryCode::INTERNATIONAL); - - // Configuration - mDevice->addMapper(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD); - InputReaderConfiguration config; - std::list unused = mDevice->configure(ARBITRARY_TIME, &config, 0); - - ASSERT_EQ(InputDeviceCountryCode::INTERNATIONAL, mDevice->getDeviceInfo().getCountryCode()); -} - TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) { ASSERT_EQ(mDevice->isEnabled(), false); } @@ -3600,6 +3586,20 @@ TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) { deviceInfo.getKeyboardLayoutInfo()->layoutType); } +TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) { + mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID, + RawLayoutInfo{.languageTag = "en", .layoutType = "extended"}); + + // Configuration + addMapperAndConfigure(AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + InputReaderConfiguration config; + std::list unused = mDevice->configure(ARBITRARY_TIME, &config, 0); + + ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag); + ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType); +} + // --- KeyboardInputMapperTest_ExternalDevice --- class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest { diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index a0910ea847..7c9be5c8d4 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -19,9 +19,6 @@ #include #include #include -#include "android/hardware/input/InputDeviceCountryCode.h" - -using android::hardware::input::InputDeviceCountryCode; constexpr size_t kValidTypes[] = {EV_SW, EV_SYN, @@ -65,46 +62,6 @@ constexpr size_t kValidCodes[] = { BTN_TASK, }; -constexpr InputDeviceCountryCode kCountryCodes[] = { - InputDeviceCountryCode::INVALID, - InputDeviceCountryCode::NOT_SUPPORTED, - InputDeviceCountryCode::ARABIC, - InputDeviceCountryCode::BELGIAN, - InputDeviceCountryCode::CANADIAN_BILINGUAL, - InputDeviceCountryCode::CANADIAN_FRENCH, - InputDeviceCountryCode::CZECH_REPUBLIC, - InputDeviceCountryCode::DANISH, - InputDeviceCountryCode::FINNISH, - InputDeviceCountryCode::FRENCH, - InputDeviceCountryCode::GERMAN, - InputDeviceCountryCode::GREEK, - InputDeviceCountryCode::HEBREW, - InputDeviceCountryCode::HUNGARY, - InputDeviceCountryCode::INTERNATIONAL, - InputDeviceCountryCode::ITALIAN, - InputDeviceCountryCode::JAPAN, - InputDeviceCountryCode::KOREAN, - InputDeviceCountryCode::LATIN_AMERICAN, - InputDeviceCountryCode::DUTCH, - InputDeviceCountryCode::NORWEGIAN, - InputDeviceCountryCode::PERSIAN, - InputDeviceCountryCode::POLAND, - InputDeviceCountryCode::PORTUGUESE, - InputDeviceCountryCode::RUSSIA, - InputDeviceCountryCode::SLOVAKIA, - InputDeviceCountryCode::SPANISH, - InputDeviceCountryCode::SWEDISH, - InputDeviceCountryCode::SWISS_FRENCH, - InputDeviceCountryCode::SWISS_GERMAN, - InputDeviceCountryCode::SWITZERLAND, - InputDeviceCountryCode::TAIWAN, - InputDeviceCountryCode::TURKISH_Q, - InputDeviceCountryCode::UK, - InputDeviceCountryCode::US, - InputDeviceCountryCode::YUGOSLAVIA, - InputDeviceCountryCode::TURKISH_F, -}; - constexpr size_t kMaxSize = 256; namespace android { @@ -197,8 +154,8 @@ public: void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map intensities) override{}; - InputDeviceCountryCode getCountryCode(int32_t deviceId) const override { - return mFdp->PickValueInArray(kCountryCodes); + std::optional getRawLayoutInfo(int32_t deviceId) const override { + return std::nullopt; }; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override { -- cgit v1.2.3-59-g8ed1b From e04ffaaaa0ded909d69b8641ca30cc8a639fc1d1 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Tue, 13 Dec 2022 23:04:04 +0000 Subject: Add an API to get the supported USI version for a display The InputManager#getHostUsiVersion(displayId) API can be used to tell if a display supports the Universal Stylus Initiative protocol for styluses, and can be used to address version compatibility issues. We first dynamically attempt to find an InputDevice associated with the display that supports USI. If there are none, we check the statically add USI version for the display in config_displayUsiVersionArray. Checking the config as a fallback means the USI InputDevice does not have be registered/open perpetually for the getHostUsiVersion() API to return the correct values. Bug: 261596890 Test: manual with device Test: atest TouchScreenTest Change-Id: Ifabd00aa996ba88258d8112e5de3582adaf27629 --- include/input/InputDevice.h | 20 +++++++++++++++----- libs/input/InputDevice.cpp | 11 +++++++---- services/inputflinger/reader/InputDevice.cpp | 3 ++- .../inputflinger/reader/mapper/TouchInputMapper.cpp | 19 ++++++++++++++----- .../inputflinger/reader/mapper/TouchInputMapper.h | 4 ++-- .../tests/PreferStylusOverTouch_test.cpp | 3 ++- .../tests/UnwantedInteractionBlocker_test.cpp | 2 +- 7 files changed, 43 insertions(+), 19 deletions(-) (limited to 'libs/input/InputDevice.cpp') diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 09933d32b1..66d3435907 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -214,6 +214,12 @@ struct KeyboardLayoutInfo { std::string layoutType; }; +// The version of the Universal Stylus Initiative (USI) protocol supported by the input device. +struct InputDeviceUsiVersion { + int32_t majorVersion = -1; + int32_t minorVersion = -1; +}; + /* * Describes the characteristics and capabilities of an input device. */ @@ -235,7 +241,7 @@ public: void initialize(int32_t id, int32_t generation, int32_t controllerNumber, const InputDeviceIdentifier& identifier, const std::string& alias, - bool isExternal, bool hasMic); + bool isExternal, bool hasMic, int32_t associatedDisplayId); inline int32_t getId() const { return mId; } inline int32_t getControllerNumber() const { return mControllerNumber; } @@ -295,8 +301,12 @@ public: std::vector getLights(); - inline void setSupportsUsi(bool supportsUsi) { mSupportsUsi = supportsUsi; } - inline bool supportsUsi() const { return mSupportsUsi; } + inline void setUsiVersion(std::optional usiVersion) { + mUsiVersion = std::move(usiVersion); + } + inline std::optional getUsiVersion() const { return mUsiVersion; } + + inline int32_t getAssociatedDisplayId() const { return mAssociatedDisplayId; } private: int32_t mId; @@ -310,8 +320,8 @@ private: uint32_t mSources; int32_t mKeyboardType; std::shared_ptr mKeyCharacterMap; - // Whether this device supports the Universal Stylus Initiative (USI) protocol for styluses. - bool mSupportsUsi; + std::optional mUsiVersion; + int32_t mAssociatedDisplayId; bool mHasVibrator; bool mHasBattery; diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 87333f2c76..9c7c0c19ed 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -166,7 +167,7 @@ std::string InputDeviceIdentifier::getCanonicalName() const { // --- InputDeviceInfo --- InputDeviceInfo::InputDeviceInfo() { - initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false); + initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false, ADISPLAY_ID_NONE); } InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) @@ -181,7 +182,8 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mSources(other.mSources), mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), - mSupportsUsi(other.mSupportsUsi), + mUsiVersion(other.mUsiVersion), + mAssociatedDisplayId(other.mAssociatedDisplayId), mHasVibrator(other.mHasVibrator), mHasBattery(other.mHasBattery), mHasButtonUnderPad(other.mHasButtonUnderPad), @@ -195,7 +197,7 @@ InputDeviceInfo::~InputDeviceInfo() { void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber, const InputDeviceIdentifier& identifier, const std::string& alias, - bool isExternal, bool hasMic) { + bool isExternal, bool hasMic, int32_t associatedDisplayId) { mId = id; mGeneration = generation; mControllerNumber = controllerNumber; @@ -205,11 +207,12 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mHasMic = hasMic; mSources = 0; mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; + mAssociatedDisplayId = associatedDisplayId; mHasVibrator = false; mHasBattery = false; mHasButtonUnderPad = false; mHasSensor = false; - mSupportsUsi = false; + mUsiVersion.reset(); mMotionRanges.clear(); mSensors.clear(); mLights.clear(); diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 6e78e82c7e..9bd50f7754 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -452,7 +452,8 @@ std::list InputDevice::updateExternalStylusState(const StylusState& InputDeviceInfo InputDevice::getDeviceInfo() { InputDeviceInfo outDeviceInfo; outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal, - mHasMic); + mHasMic, getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE)); + for_each_mapper( [&outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(&outDeviceInfo); }); diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 4d51aeef5d..31287a3a78 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -55,6 +55,10 @@ static bool isPointInRect(const Rect& rect, vec2 p) { return p.x >= rect.left && p.x < rect.right && p.y >= rect.top && p.y < rect.bottom; } +static std::string toString(const InputDeviceUsiVersion& v) { + return base::StringPrintf("%d.%d", v.majorVersion, v.minorVersion); +} + template inline static void swap(T& a, T& b) { T temp = a; @@ -188,7 +192,7 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) { info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f); } info->setButtonUnderPad(mParameters.hasButtonUnderPad); - info->setSupportsUsi(mParameters.supportsUsi); + info->setUsiVersion(mParameters.usiVersion); } void TouchInputMapper::dump(std::string& dump) { @@ -421,9 +425,13 @@ void TouchInputMapper::configureParameters() { mParameters.wake = getDeviceContext().isExternal(); getDeviceContext().getConfiguration().tryGetProperty("touch.wake", mParameters.wake); - mParameters.supportsUsi = false; - getDeviceContext().getConfiguration().tryGetProperty("touch.supportsUsi", - mParameters.supportsUsi); + InputDeviceUsiVersion usiVersion; + if (getDeviceContext().getConfiguration().tryGetProperty("touch.usiVersionMajor", + usiVersion.majorVersion) && + getDeviceContext().getConfiguration().tryGetProperty("touch.usiVersionMinor", + usiVersion.minorVersion)) { + mParameters.usiVersion = usiVersion; + } mParameters.enableForInactiveViewport = false; getDeviceContext().getConfiguration().tryGetProperty("touch.enableForInactiveViewport", @@ -472,7 +480,8 @@ void TouchInputMapper::dumpParameters(std::string& dump) { mParameters.uniqueDisplayId.c_str()); dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware)); dump += INDENT4 "Orientation: " + ftl::enum_string(mParameters.orientation) + "\n"; - dump += StringPrintf(INDENT4 "SupportsUsi: %s\n", toString(mParameters.supportsUsi)); + dump += StringPrintf(INDENT4 "UsiVersion: %s\n", + toString(mParameters.usiVersion, toString).c_str()); dump += StringPrintf(INDENT4 "EnableForInactiveViewport: %s\n", toString(mParameters.enableForInactiveViewport)); } diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index 6e35b460af..87deb39e20 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -234,8 +234,8 @@ protected: bool wake; - // Whether the device supports the Universal Stylus Initiative (USI) protocol for styluses. - bool supportsUsi; + // The Universal Stylus Initiative (USI) protocol version supported by this device. + std::optional usiVersion; // Allows touches while the display is off. bool enableForInactiveViewport; diff --git a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp index bd053603df..7265362a7c 100644 --- a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp +++ b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp @@ -15,6 +15,7 @@ */ #include +#include #include "../PreferStylusOverTouchBlocker.h" namespace android { @@ -438,7 +439,7 @@ TEST_F(PreferStylusOverTouchTest, MixedStylusAndTouchDeviceIsCanceledAtFirst) { InputDeviceInfo stylusDevice; stylusDevice.initialize(STYLUS_DEVICE_ID, 1 /*generation*/, 1 /*controllerNumber*/, {} /*identifier*/, "stylus device", false /*external*/, - false /*hasMic*/); + false /*hasMic*/, ADISPLAY_ID_NONE); notifyInputDevicesChanged({stylusDevice}); // The touchscreen device was removed, so we no longer remember anything about it. We should // again start blocking touch events from it. diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp index 4c84160a1d..e12f88ef40 100644 --- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp +++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp @@ -105,7 +105,7 @@ static InputDeviceInfo generateTestDeviceInfo() { auto info = InputDeviceInfo(); info.initialize(DEVICE_ID, /*generation*/ 1, /*controllerNumber*/ 1, identifier, "alias", - /*isExternal*/ false, /*hasMic*/ false); + /*isExternal*/ false, /*hasMic*/ false, ADISPLAY_ID_NONE); info.addSource(AINPUT_SOURCE_TOUCHSCREEN); info.addMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN, 0, 1599, /*flat*/ 0, /*fuzz*/ 0, X_RESOLUTION); -- cgit v1.2.3-59-g8ed1b