diff options
| -rw-r--r-- | include/input/InputDevice.h | 11 | ||||
| -rw-r--r-- | libs/input/Android.bp | 1 | ||||
| -rw-r--r-- | libs/input/InputDevice.cpp | 7 | ||||
| -rw-r--r-- | libs/input/android/hardware/input/InputDeviceCountryCode.aidl | 212 | ||||
| -rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 32 | ||||
| -rw-r--r-- | services/inputflinger/reader/InputDevice.cpp | 15 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/EventHub.h | 11 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/InputDevice.h | 4 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 28 |
9 files changed, 312 insertions, 9 deletions
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 <unordered_map> #include <vector> +#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<KeyCharacterMap> 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 <input/InputEventLabels.h> 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 { @@ -302,6 +303,24 @@ static std::optional<std::array<LightColor, COLOR_NUM>> getColorIndexArray( } /** + * 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<int>(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<InputDeviceCountryCode>(hidCountryCode); +} + +/** * Read information about batteries exposed through the sysfs path. */ static std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> readBatteryConfiguration( @@ -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<std::string>& devices) { std::scoped_lock _l(mLock); @@ -1384,6 +1412,7 @@ std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDevi return std::make_shared<AssociatedDevice>( 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<InputDeviceClass>(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<LightColor, int32_t> 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<LightColor, int32_t> intensities) override final; + hardware::input::InputDeviceCountryCode getCountryCode(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; @@ -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<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos; std::unordered_map<int32_t /*lightId*/, RawLightInfo> 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<InputDeviceClass> mClasses; @@ -311,6 +312,9 @@ public: } inline std::vector<TouchVideoFrame> 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 <gtest/gtest.h> #include <gui/constants.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; @@ -455,6 +458,7 @@ class FakeEventHub : public EventHubInterface { BitArray<MSC_MAX> mscBitmask; std::vector<VirtualKeyDefinition> 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<InputDeviceClass>(0), mDevice->getClasses()); } +TEST_F(InputDeviceTest, CountryCodeCorrectlyMapped) { + mFakeEventHub->setCountryCode(EVENTHUB_ID, InputDeviceCountryCode::INTERNATIONAL); + + // Configuration + mDevice->addMapper<FakeInputMapper>(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); } |