xref: /aosp_15_r20/frameworks/native/libs/input/Keyboard.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "Keyboard"
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <limits.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <stdlib.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <optional>
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include <input/InputDevice.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <input/InputEventLabels.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <input/KeyCharacterMap.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <input/KeyLayoutMap.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <input/Keyboard.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <utils/Errors.h>
31*38e8c45fSAndroid Build Coastguard Worker 
32*38e8c45fSAndroid Build Coastguard Worker namespace android {
33*38e8c45fSAndroid Build Coastguard Worker 
getPath(const InputDeviceIdentifier & deviceIdentifier,const std::string & name,InputDeviceConfigurationFileType type)34*38e8c45fSAndroid Build Coastguard Worker static std::string getPath(const InputDeviceIdentifier& deviceIdentifier, const std::string& name,
35*38e8c45fSAndroid Build Coastguard Worker                            InputDeviceConfigurationFileType type) {
36*38e8c45fSAndroid Build Coastguard Worker     return name.empty()
37*38e8c45fSAndroid Build Coastguard Worker             ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
38*38e8c45fSAndroid Build Coastguard Worker             : getInputDeviceConfigurationFilePathByName(name, type);
39*38e8c45fSAndroid Build Coastguard Worker }
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker // --- KeyMap ---
42*38e8c45fSAndroid Build Coastguard Worker 
KeyMap()43*38e8c45fSAndroid Build Coastguard Worker KeyMap::KeyMap() {
44*38e8c45fSAndroid Build Coastguard Worker }
45*38e8c45fSAndroid Build Coastguard Worker 
~KeyMap()46*38e8c45fSAndroid Build Coastguard Worker KeyMap::~KeyMap() {
47*38e8c45fSAndroid Build Coastguard Worker }
48*38e8c45fSAndroid Build Coastguard Worker 
load(const InputDeviceIdentifier & deviceIdentifier,const PropertyMap * deviceConfiguration)49*38e8c45fSAndroid Build Coastguard Worker status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier,
50*38e8c45fSAndroid Build Coastguard Worker         const PropertyMap* deviceConfiguration) {
51*38e8c45fSAndroid Build Coastguard Worker     // Use the configured key layout if available.
52*38e8c45fSAndroid Build Coastguard Worker     if (deviceConfiguration) {
53*38e8c45fSAndroid Build Coastguard Worker         std::optional<std::string> keyLayoutName =
54*38e8c45fSAndroid Build Coastguard Worker                 deviceConfiguration->getString("keyboard.layout");
55*38e8c45fSAndroid Build Coastguard Worker         if (keyLayoutName.has_value()) {
56*38e8c45fSAndroid Build Coastguard Worker             status_t status = loadKeyLayout(deviceIdentifier, *keyLayoutName);
57*38e8c45fSAndroid Build Coastguard Worker             if (status == NAME_NOT_FOUND) {
58*38e8c45fSAndroid Build Coastguard Worker                 ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
59*38e8c45fSAndroid Build Coastguard Worker                       "it was not found.",
60*38e8c45fSAndroid Build Coastguard Worker                       deviceIdentifier.name.c_str(), keyLayoutName->c_str());
61*38e8c45fSAndroid Build Coastguard Worker             }
62*38e8c45fSAndroid Build Coastguard Worker         }
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker         std::optional<std::string> keyCharacterMapName =
65*38e8c45fSAndroid Build Coastguard Worker                 deviceConfiguration->getString("keyboard.characterMap");
66*38e8c45fSAndroid Build Coastguard Worker         if (keyCharacterMapName.has_value()) {
67*38e8c45fSAndroid Build Coastguard Worker             status_t status = loadKeyCharacterMap(deviceIdentifier, *keyCharacterMapName);
68*38e8c45fSAndroid Build Coastguard Worker             if (status == NAME_NOT_FOUND) {
69*38e8c45fSAndroid Build Coastguard Worker                 ALOGE("Configuration for keyboard device '%s' requested keyboard character "
70*38e8c45fSAndroid Build Coastguard Worker                       "map '%s' but it was not found.",
71*38e8c45fSAndroid Build Coastguard Worker                       deviceIdentifier.name.c_str(), keyCharacterMapName->c_str());
72*38e8c45fSAndroid Build Coastguard Worker             }
73*38e8c45fSAndroid Build Coastguard Worker         }
74*38e8c45fSAndroid Build Coastguard Worker 
75*38e8c45fSAndroid Build Coastguard Worker         if (isComplete()) {
76*38e8c45fSAndroid Build Coastguard Worker             return OK;
77*38e8c45fSAndroid Build Coastguard Worker         }
78*38e8c45fSAndroid Build Coastguard Worker     }
79*38e8c45fSAndroid Build Coastguard Worker 
80*38e8c45fSAndroid Build Coastguard Worker     // Try searching by device identifier.
81*38e8c45fSAndroid Build Coastguard Worker     if (probeKeyMap(deviceIdentifier, "")) {
82*38e8c45fSAndroid Build Coastguard Worker         return OK;
83*38e8c45fSAndroid Build Coastguard Worker     }
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker     // Fall back on the Generic key map.
86*38e8c45fSAndroid Build Coastguard Worker     // TODO Apply some additional heuristics here to figure out what kind of
87*38e8c45fSAndroid Build Coastguard Worker     //      generic key map to use (US English, etc.) for typical external keyboards.
88*38e8c45fSAndroid Build Coastguard Worker     if (probeKeyMap(deviceIdentifier, "Generic")) {
89*38e8c45fSAndroid Build Coastguard Worker         return OK;
90*38e8c45fSAndroid Build Coastguard Worker     }
91*38e8c45fSAndroid Build Coastguard Worker 
92*38e8c45fSAndroid Build Coastguard Worker     // Try the Virtual key map as a last resort.
93*38e8c45fSAndroid Build Coastguard Worker     if (probeKeyMap(deviceIdentifier, "Virtual")) {
94*38e8c45fSAndroid Build Coastguard Worker         return OK;
95*38e8c45fSAndroid Build Coastguard Worker     }
96*38e8c45fSAndroid Build Coastguard Worker 
97*38e8c45fSAndroid Build Coastguard Worker     // Give up!
98*38e8c45fSAndroid Build Coastguard Worker     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
99*38e8c45fSAndroid Build Coastguard Worker             deviceIdentifier.name.c_str());
100*38e8c45fSAndroid Build Coastguard Worker     return NAME_NOT_FOUND;
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker 
probeKeyMap(const InputDeviceIdentifier & deviceIdentifier,const std::string & keyMapName)103*38e8c45fSAndroid Build Coastguard Worker bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
104*38e8c45fSAndroid Build Coastguard Worker         const std::string& keyMapName) {
105*38e8c45fSAndroid Build Coastguard Worker     if (!haveKeyLayout()) {
106*38e8c45fSAndroid Build Coastguard Worker         loadKeyLayout(deviceIdentifier, keyMapName);
107*38e8c45fSAndroid Build Coastguard Worker     }
108*38e8c45fSAndroid Build Coastguard Worker     if (!haveKeyCharacterMap()) {
109*38e8c45fSAndroid Build Coastguard Worker         loadKeyCharacterMap(deviceIdentifier, keyMapName);
110*38e8c45fSAndroid Build Coastguard Worker     }
111*38e8c45fSAndroid Build Coastguard Worker     return isComplete();
112*38e8c45fSAndroid Build Coastguard Worker }
113*38e8c45fSAndroid Build Coastguard Worker 
loadKeyLayout(const InputDeviceIdentifier & deviceIdentifier,const std::string & name)114*38e8c45fSAndroid Build Coastguard Worker status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
115*38e8c45fSAndroid Build Coastguard Worker         const std::string& name) {
116*38e8c45fSAndroid Build Coastguard Worker     std::string path(getPath(deviceIdentifier, name, InputDeviceConfigurationFileType::KEY_LAYOUT));
117*38e8c45fSAndroid Build Coastguard Worker     if (path.empty()) {
118*38e8c45fSAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
119*38e8c45fSAndroid Build Coastguard Worker     }
120*38e8c45fSAndroid Build Coastguard Worker 
121*38e8c45fSAndroid Build Coastguard Worker     base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(path);
122*38e8c45fSAndroid Build Coastguard Worker     if (ret.ok()) {
123*38e8c45fSAndroid Build Coastguard Worker         keyLayoutMap = *ret;
124*38e8c45fSAndroid Build Coastguard Worker         keyLayoutFile = path;
125*38e8c45fSAndroid Build Coastguard Worker         return OK;
126*38e8c45fSAndroid Build Coastguard Worker     }
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker     // Try to load fallback layout if the regular layout could not be loaded due to missing
129*38e8c45fSAndroid Build Coastguard Worker     // kernel modules
130*38e8c45fSAndroid Build Coastguard Worker     std::string fallbackPath(
131*38e8c45fSAndroid Build Coastguard Worker             getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier,
132*38e8c45fSAndroid Build Coastguard Worker                                                                   InputDeviceConfigurationFileType::
133*38e8c45fSAndroid Build Coastguard Worker                                                                           KEY_LAYOUT,
134*38e8c45fSAndroid Build Coastguard Worker                                                                   "_fallback"));
135*38e8c45fSAndroid Build Coastguard Worker     ret = KeyLayoutMap::load(fallbackPath);
136*38e8c45fSAndroid Build Coastguard Worker     if (!ret.ok()) {
137*38e8c45fSAndroid Build Coastguard Worker         return ret.error().code();
138*38e8c45fSAndroid Build Coastguard Worker     }
139*38e8c45fSAndroid Build Coastguard Worker     keyLayoutMap = *ret;
140*38e8c45fSAndroid Build Coastguard Worker     keyLayoutFile = fallbackPath;
141*38e8c45fSAndroid Build Coastguard Worker     return OK;
142*38e8c45fSAndroid Build Coastguard Worker }
143*38e8c45fSAndroid Build Coastguard Worker 
loadKeyCharacterMap(const InputDeviceIdentifier & deviceIdentifier,const std::string & name)144*38e8c45fSAndroid Build Coastguard Worker status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
145*38e8c45fSAndroid Build Coastguard Worker         const std::string& name) {
146*38e8c45fSAndroid Build Coastguard Worker     std::string path =
147*38e8c45fSAndroid Build Coastguard Worker             getPath(deviceIdentifier, name, InputDeviceConfigurationFileType::KEY_CHARACTER_MAP);
148*38e8c45fSAndroid Build Coastguard Worker     if (path.empty()) {
149*38e8c45fSAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
150*38e8c45fSAndroid Build Coastguard Worker     }
151*38e8c45fSAndroid Build Coastguard Worker 
152*38e8c45fSAndroid Build Coastguard Worker     base::Result<std::shared_ptr<KeyCharacterMap>> ret =
153*38e8c45fSAndroid Build Coastguard Worker             KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE);
154*38e8c45fSAndroid Build Coastguard Worker     if (!ret.ok()) {
155*38e8c45fSAndroid Build Coastguard Worker         return ret.error().code();
156*38e8c45fSAndroid Build Coastguard Worker     }
157*38e8c45fSAndroid Build Coastguard Worker     keyCharacterMap = *ret;
158*38e8c45fSAndroid Build Coastguard Worker     keyCharacterMapFile = path;
159*38e8c45fSAndroid Build Coastguard Worker     return OK;
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker 
162*38e8c45fSAndroid Build Coastguard Worker // --- Global functions ---
163*38e8c45fSAndroid Build Coastguard Worker 
isKeyboardSpecialFunction(const PropertyMap * config)164*38e8c45fSAndroid Build Coastguard Worker bool isKeyboardSpecialFunction(const PropertyMap* config) {
165*38e8c45fSAndroid Build Coastguard Worker     if (config == nullptr) {
166*38e8c45fSAndroid Build Coastguard Worker         return false;
167*38e8c45fSAndroid Build Coastguard Worker     }
168*38e8c45fSAndroid Build Coastguard Worker     return config->getBool("keyboard.specialFunction").value_or(false);
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker 
isEligibleBuiltInKeyboard(const InputDeviceIdentifier & deviceIdentifier,const PropertyMap * deviceConfiguration,const KeyMap * keyMap)171*38e8c45fSAndroid Build Coastguard Worker bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
172*38e8c45fSAndroid Build Coastguard Worker         const PropertyMap* deviceConfiguration, const KeyMap* keyMap) {
173*38e8c45fSAndroid Build Coastguard Worker     // TODO: remove the third OR statement (SPECIAL_FUNCTION) in Q
174*38e8c45fSAndroid Build Coastguard Worker     if (!keyMap->haveKeyCharacterMap() || isKeyboardSpecialFunction(deviceConfiguration) ||
175*38e8c45fSAndroid Build Coastguard Worker         keyMap->keyCharacterMap->getKeyboardType() ==
176*38e8c45fSAndroid Build Coastguard Worker                 KeyCharacterMap::KeyboardType::SPECIAL_FUNCTION) {
177*38e8c45fSAndroid Build Coastguard Worker         return false;
178*38e8c45fSAndroid Build Coastguard Worker     }
179*38e8c45fSAndroid Build Coastguard Worker 
180*38e8c45fSAndroid Build Coastguard Worker     if (deviceConfiguration) {
181*38e8c45fSAndroid Build Coastguard Worker         if (deviceConfiguration->getBool("keyboard.builtIn").value_or(false)) {
182*38e8c45fSAndroid Build Coastguard Worker             return true;
183*38e8c45fSAndroid Build Coastguard Worker         }
184*38e8c45fSAndroid Build Coastguard Worker     }
185*38e8c45fSAndroid Build Coastguard Worker 
186*38e8c45fSAndroid Build Coastguard Worker     return strstr(deviceIdentifier.name.c_str(), "-keypad");
187*38e8c45fSAndroid Build Coastguard Worker }
188*38e8c45fSAndroid Build Coastguard Worker 
setEphemeralMetaState(int32_t mask,bool down,int32_t oldMetaState)189*38e8c45fSAndroid Build Coastguard Worker static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
190*38e8c45fSAndroid Build Coastguard Worker     int32_t newMetaState;
191*38e8c45fSAndroid Build Coastguard Worker     if (down) {
192*38e8c45fSAndroid Build Coastguard Worker         newMetaState = oldMetaState | mask;
193*38e8c45fSAndroid Build Coastguard Worker     } else {
194*38e8c45fSAndroid Build Coastguard Worker         newMetaState = oldMetaState &
195*38e8c45fSAndroid Build Coastguard Worker                 ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
196*38e8c45fSAndroid Build Coastguard Worker     }
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker     return normalizeMetaState(newMetaState);
199*38e8c45fSAndroid Build Coastguard Worker }
200*38e8c45fSAndroid Build Coastguard Worker 
normalizeMetaState(int32_t oldMetaState)201*38e8c45fSAndroid Build Coastguard Worker int32_t normalizeMetaState(int32_t oldMetaState) {
202*38e8c45fSAndroid Build Coastguard Worker     int32_t newMetaState = oldMetaState;
203*38e8c45fSAndroid Build Coastguard Worker     if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
204*38e8c45fSAndroid Build Coastguard Worker         newMetaState |= AMETA_ALT_ON;
205*38e8c45fSAndroid Build Coastguard Worker     }
206*38e8c45fSAndroid Build Coastguard Worker 
207*38e8c45fSAndroid Build Coastguard Worker     if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
208*38e8c45fSAndroid Build Coastguard Worker         newMetaState |= AMETA_SHIFT_ON;
209*38e8c45fSAndroid Build Coastguard Worker     }
210*38e8c45fSAndroid Build Coastguard Worker 
211*38e8c45fSAndroid Build Coastguard Worker     if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
212*38e8c45fSAndroid Build Coastguard Worker         newMetaState |= AMETA_CTRL_ON;
213*38e8c45fSAndroid Build Coastguard Worker     }
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker     if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
216*38e8c45fSAndroid Build Coastguard Worker         newMetaState |= AMETA_META_ON;
217*38e8c45fSAndroid Build Coastguard Worker     }
218*38e8c45fSAndroid Build Coastguard Worker     return newMetaState;
219*38e8c45fSAndroid Build Coastguard Worker }
220*38e8c45fSAndroid Build Coastguard Worker 
toggleLockedMetaState(int32_t mask,bool down,int32_t oldMetaState)221*38e8c45fSAndroid Build Coastguard Worker static int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) {
222*38e8c45fSAndroid Build Coastguard Worker     if (down) {
223*38e8c45fSAndroid Build Coastguard Worker         return oldMetaState;
224*38e8c45fSAndroid Build Coastguard Worker     } else {
225*38e8c45fSAndroid Build Coastguard Worker         return oldMetaState ^ mask;
226*38e8c45fSAndroid Build Coastguard Worker     }
227*38e8c45fSAndroid Build Coastguard Worker }
228*38e8c45fSAndroid Build Coastguard Worker 
updateMetaState(int32_t keyCode,bool down,int32_t oldMetaState)229*38e8c45fSAndroid Build Coastguard Worker int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
230*38e8c45fSAndroid Build Coastguard Worker     switch (keyCode) {
231*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_ALT_LEFT:
232*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
233*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_ALT_RIGHT:
234*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState);
235*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SHIFT_LEFT:
236*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState);
237*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SHIFT_RIGHT:
238*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState);
239*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SYM:
240*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState);
241*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_FUNCTION:
242*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState);
243*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_CTRL_LEFT:
244*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState);
245*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_CTRL_RIGHT:
246*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState);
247*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_META_LEFT:
248*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState);
249*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_META_RIGHT:
250*38e8c45fSAndroid Build Coastguard Worker         return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState);
251*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_CAPS_LOCK:
252*38e8c45fSAndroid Build Coastguard Worker         return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState);
253*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_NUM_LOCK:
254*38e8c45fSAndroid Build Coastguard Worker         return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState);
255*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SCROLL_LOCK:
256*38e8c45fSAndroid Build Coastguard Worker         return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState);
257*38e8c45fSAndroid Build Coastguard Worker     default:
258*38e8c45fSAndroid Build Coastguard Worker         return oldMetaState;
259*38e8c45fSAndroid Build Coastguard Worker     }
260*38e8c45fSAndroid Build Coastguard Worker }
261*38e8c45fSAndroid Build Coastguard Worker 
isMetaKey(int32_t keyCode)262*38e8c45fSAndroid Build Coastguard Worker bool isMetaKey(int32_t keyCode) {
263*38e8c45fSAndroid Build Coastguard Worker     switch (keyCode) {
264*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_ALT_LEFT:
265*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_ALT_RIGHT:
266*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SHIFT_LEFT:
267*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SHIFT_RIGHT:
268*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SYM:
269*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_FUNCTION:
270*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_CTRL_LEFT:
271*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_CTRL_RIGHT:
272*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_META_LEFT:
273*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_META_RIGHT:
274*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_CAPS_LOCK:
275*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_NUM_LOCK:
276*38e8c45fSAndroid Build Coastguard Worker     case AKEYCODE_SCROLL_LOCK:
277*38e8c45fSAndroid Build Coastguard Worker         return true;
278*38e8c45fSAndroid Build Coastguard Worker     default:
279*38e8c45fSAndroid Build Coastguard Worker         return false;
280*38e8c45fSAndroid Build Coastguard Worker     }
281*38e8c45fSAndroid Build Coastguard Worker }
282*38e8c45fSAndroid Build Coastguard Worker 
283*38e8c45fSAndroid Build Coastguard Worker 
284*38e8c45fSAndroid Build Coastguard Worker } // namespace android
285