• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "InputDevice"
18 
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <ctype.h>
22 
23 #include <android-base/stringprintf.h>
24 #include <input/InputDevice.h>
25 #include <input/InputEventLabels.h>
26 #include <input/NamedEnum.h>
27 
28 using android::base::StringPrintf;
29 
30 namespace android {
31 
32 static const char* CONFIGURATION_FILE_DIR[] = {
33         "idc/",
34         "keylayout/",
35         "keychars/",
36 };
37 
38 static const char* CONFIGURATION_FILE_EXTENSION[] = {
39         ".idc",
40         ".kl",
41         ".kcm",
42 };
43 
isValidNameChar(char ch)44 static bool isValidNameChar(char ch) {
45     return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
46 }
47 
appendInputDeviceConfigurationFileRelativePath(std::string & path,const std::string & name,InputDeviceConfigurationFileType type)48 static void appendInputDeviceConfigurationFileRelativePath(std::string& path,
49         const std::string& name, InputDeviceConfigurationFileType type) {
50     path += CONFIGURATION_FILE_DIR[static_cast<int32_t>(type)];
51     path += name;
52     path += CONFIGURATION_FILE_EXTENSION[static_cast<int32_t>(type)];
53 }
54 
getInputDeviceConfigurationFilePathByDeviceIdentifier(const InputDeviceIdentifier & deviceIdentifier,InputDeviceConfigurationFileType type)55 std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
56         const InputDeviceIdentifier& deviceIdentifier,
57         InputDeviceConfigurationFileType type) {
58     if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
59         if (deviceIdentifier.version != 0) {
60             // Try vendor product version.
61             std::string versionPath = getInputDeviceConfigurationFilePathByName(
62                     StringPrintf("Vendor_%04x_Product_%04x_Version_%04x",
63                             deviceIdentifier.vendor, deviceIdentifier.product,
64                             deviceIdentifier.version),
65                     type);
66             if (!versionPath.empty()) {
67                 return versionPath;
68             }
69         }
70 
71         // Try vendor product.
72         std::string productPath = getInputDeviceConfigurationFilePathByName(
73                 StringPrintf("Vendor_%04x_Product_%04x",
74                         deviceIdentifier.vendor, deviceIdentifier.product),
75                 type);
76         if (!productPath.empty()) {
77             return productPath;
78         }
79     }
80 
81     // Try device name.
82     return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName(), type);
83 }
84 
getInputDeviceConfigurationFilePathByName(const std::string & name,InputDeviceConfigurationFileType type)85 std::string getInputDeviceConfigurationFilePathByName(
86         const std::string& name, InputDeviceConfigurationFileType type) {
87     // Search system repository.
88     std::string path;
89 
90     // Treblized input device config files will be located /product/usr, /system_ext/usr,
91     // /odm/usr or /vendor/usr.
92     const char* rootsForPartition[]{"/product", "/system_ext", "/odm", "/vendor",
93                                     getenv("ANDROID_ROOT")};
94     for (size_t i = 0; i < size(rootsForPartition); i++) {
95         if (rootsForPartition[i] == nullptr) {
96             continue;
97         }
98         path = rootsForPartition[i];
99         path += "/usr/";
100         appendInputDeviceConfigurationFileRelativePath(path, name, type);
101 #if DEBUG_PROBE
102         ALOGD("Probing for system provided input device configuration file: path='%s'",
103               path.c_str());
104 #endif
105         if (!access(path.c_str(), R_OK)) {
106 #if DEBUG_PROBE
107             ALOGD("Found");
108 #endif
109             return path;
110         }
111     }
112 
113     // Search user repository.
114     // TODO Should only look here if not in safe mode.
115     path = "";
116     char *androidData = getenv("ANDROID_DATA");
117     if (androidData != nullptr) {
118         path += androidData;
119     }
120     path += "/system/devices/";
121     appendInputDeviceConfigurationFileRelativePath(path, name, type);
122 #if DEBUG_PROBE
123     ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
124 #endif
125     if (!access(path.c_str(), R_OK)) {
126 #if DEBUG_PROBE
127         ALOGD("Found");
128 #endif
129         return path;
130     }
131 
132     // Not found.
133 #if DEBUG_PROBE
134     ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
135             name.c_str(), type);
136 #endif
137     return "";
138 }
139 
140 // --- InputDeviceIdentifier
141 
getCanonicalName() const142 std::string InputDeviceIdentifier::getCanonicalName() const {
143     std::string replacedName = name;
144     for (char& ch : replacedName) {
145         if (!isValidNameChar(ch)) {
146             ch = '_';
147         }
148     }
149     return replacedName;
150 }
151 
152 
153 // --- InputDeviceInfo ---
154 
InputDeviceInfo()155 InputDeviceInfo::InputDeviceInfo() {
156     initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false);
157 }
158 
InputDeviceInfo(const InputDeviceInfo & other)159 InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other)
160       : mId(other.mId),
161         mGeneration(other.mGeneration),
162         mControllerNumber(other.mControllerNumber),
163         mIdentifier(other.mIdentifier),
164         mAlias(other.mAlias),
165         mIsExternal(other.mIsExternal),
166         mHasMic(other.mHasMic),
167         mSources(other.mSources),
168         mKeyboardType(other.mKeyboardType),
169         mKeyCharacterMap(other.mKeyCharacterMap),
170         mHasVibrator(other.mHasVibrator),
171         mHasBattery(other.mHasBattery),
172         mHasButtonUnderPad(other.mHasButtonUnderPad),
173         mHasSensor(other.mHasSensor),
174         mMotionRanges(other.mMotionRanges),
175         mSensors(other.mSensors),
176         mLights(other.mLights) {}
177 
~InputDeviceInfo()178 InputDeviceInfo::~InputDeviceInfo() {
179 }
180 
initialize(int32_t id,int32_t generation,int32_t controllerNumber,const InputDeviceIdentifier & identifier,const std::string & alias,bool isExternal,bool hasMic)181 void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
182         const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal,
183         bool hasMic) {
184     mId = id;
185     mGeneration = generation;
186     mControllerNumber = controllerNumber;
187     mIdentifier = identifier;
188     mAlias = alias;
189     mIsExternal = isExternal;
190     mHasMic = hasMic;
191     mSources = 0;
192     mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
193     mHasVibrator = false;
194     mHasBattery = false;
195     mHasButtonUnderPad = false;
196     mHasSensor = false;
197     mMotionRanges.clear();
198     mSensors.clear();
199     mLights.clear();
200 }
201 
getMotionRange(int32_t axis,uint32_t source) const202 const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
203         int32_t axis, uint32_t source) const {
204     size_t numRanges = mMotionRanges.size();
205     for (size_t i = 0; i < numRanges; i++) {
206         const MotionRange& range = mMotionRanges[i];
207         if (range.axis == axis && range.source == source) {
208             return &range;
209         }
210     }
211     return nullptr;
212 }
213 
addSource(uint32_t source)214 void InputDeviceInfo::addSource(uint32_t source) {
215     mSources |= source;
216 }
217 
addMotionRange(int32_t axis,uint32_t source,float min,float max,float flat,float fuzz,float resolution)218 void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
219         float flat, float fuzz, float resolution) {
220     MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
221     mMotionRanges.push_back(range);
222 }
223 
addMotionRange(const MotionRange & range)224 void InputDeviceInfo::addMotionRange(const MotionRange& range) {
225     mMotionRanges.push_back(range);
226 }
227 
addSensorInfo(const InputDeviceSensorInfo & info)228 void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) {
229     if (mSensors.find(info.type) != mSensors.end()) {
230         ALOGW("Sensor type %s already exists, will be replaced by new sensor added.",
231               NamedEnum::string(info.type).c_str());
232     }
233     mSensors.insert_or_assign(info.type, info);
234 }
235 
addBatteryInfo(const InputDeviceBatteryInfo & info)236 void InputDeviceInfo::addBatteryInfo(const InputDeviceBatteryInfo& info) {
237     if (mBatteries.find(info.id) != mBatteries.end()) {
238         ALOGW("Battery id %d already exists, will be replaced by new battery added.", info.id);
239     }
240     mBatteries.insert_or_assign(info.id, info);
241 }
242 
addLightInfo(const InputDeviceLightInfo & info)243 void InputDeviceInfo::addLightInfo(const InputDeviceLightInfo& info) {
244     if (mLights.find(info.id) != mLights.end()) {
245         ALOGW("Light id %d already exists, will be replaced by new light added.", info.id);
246     }
247     mLights.insert_or_assign(info.id, info);
248 }
249 
getSensors()250 std::vector<InputDeviceSensorInfo> InputDeviceInfo::getSensors() {
251     std::vector<InputDeviceSensorInfo> infos;
252     infos.reserve(mSensors.size());
253     for (const auto& [type, info] : mSensors) {
254         infos.push_back(info);
255     }
256     return infos;
257 }
258 
getLights()259 std::vector<InputDeviceLightInfo> InputDeviceInfo::getLights() {
260     std::vector<InputDeviceLightInfo> infos;
261     infos.reserve(mLights.size());
262     for (const auto& [id, info] : mLights) {
263         infos.push_back(info);
264     }
265     return infos;
266 }
267 
268 } // namespace android
269