1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2008 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 #pragma once 18*38e8c45fSAndroid Build Coastguard Worker 19*38e8c45fSAndroid Build Coastguard Worker #include <stdint.h> 20*38e8c45fSAndroid Build Coastguard Worker #include <list> 21*38e8c45fSAndroid Build Coastguard Worker 22*38e8c45fSAndroid Build Coastguard Worker #include <binder/IBinder.h> 23*38e8c45fSAndroid Build Coastguard Worker 24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/result.h> 25*38e8c45fSAndroid Build Coastguard Worker #include <input/Input.h> 26*38e8c45fSAndroid Build Coastguard Worker #include <utils/Errors.h> 27*38e8c45fSAndroid Build Coastguard Worker #include <utils/Tokenizer.h> 28*38e8c45fSAndroid Build Coastguard Worker #include <utils/Unicode.h> 29*38e8c45fSAndroid Build Coastguard Worker #include <map> 30*38e8c45fSAndroid Build Coastguard Worker 31*38e8c45fSAndroid Build Coastguard Worker // Maximum number of keys supported by KeyCharacterMaps 32*38e8c45fSAndroid Build Coastguard Worker #define MAX_KEYS 8192 33*38e8c45fSAndroid Build Coastguard Worker 34*38e8c45fSAndroid Build Coastguard Worker namespace android { 35*38e8c45fSAndroid Build Coastguard Worker 36*38e8c45fSAndroid Build Coastguard Worker /** 37*38e8c45fSAndroid Build Coastguard Worker * Describes a mapping from Android key codes to characters. 38*38e8c45fSAndroid Build Coastguard Worker * Also specifies other functions of the keyboard such as the keyboard type 39*38e8c45fSAndroid Build Coastguard Worker * and key modifier semantics. 40*38e8c45fSAndroid Build Coastguard Worker * 41*38e8c45fSAndroid Build Coastguard Worker * This object is immutable after it has been loaded. 42*38e8c45fSAndroid Build Coastguard Worker */ 43*38e8c45fSAndroid Build Coastguard Worker class KeyCharacterMap { 44*38e8c45fSAndroid Build Coastguard Worker public: 45*38e8c45fSAndroid Build Coastguard Worker enum class KeyboardType : int32_t { 46*38e8c45fSAndroid Build Coastguard Worker UNKNOWN = 0, 47*38e8c45fSAndroid Build Coastguard Worker NUMERIC = 1, 48*38e8c45fSAndroid Build Coastguard Worker PREDICTIVE = 2, 49*38e8c45fSAndroid Build Coastguard Worker ALPHA = 3, 50*38e8c45fSAndroid Build Coastguard Worker FULL = 4, 51*38e8c45fSAndroid Build Coastguard Worker /** 52*38e8c45fSAndroid Build Coastguard Worker * Deprecated. Set 'keyboard.specialFunction' to '1' in the device's IDC file instead. 53*38e8c45fSAndroid Build Coastguard Worker */ 54*38e8c45fSAndroid Build Coastguard Worker SPECIAL_FUNCTION = 5, 55*38e8c45fSAndroid Build Coastguard Worker OVERLAY = 6, 56*38e8c45fSAndroid Build Coastguard Worker }; 57*38e8c45fSAndroid Build Coastguard Worker 58*38e8c45fSAndroid Build Coastguard Worker enum class Format { 59*38e8c45fSAndroid Build Coastguard Worker // Base keyboard layout, may contain device-specific options, such as "type" declaration. 60*38e8c45fSAndroid Build Coastguard Worker BASE = 0, 61*38e8c45fSAndroid Build Coastguard Worker // Overlay keyboard layout, more restrictive, may be published by applications, 62*38e8c45fSAndroid Build Coastguard Worker // cannot override device-specific options. 63*38e8c45fSAndroid Build Coastguard Worker OVERLAY = 1, 64*38e8c45fSAndroid Build Coastguard Worker // Either base or overlay layout ok. 65*38e8c45fSAndroid Build Coastguard Worker ANY = 2, 66*38e8c45fSAndroid Build Coastguard Worker }; 67*38e8c45fSAndroid Build Coastguard Worker 68*38e8c45fSAndroid Build Coastguard Worker // Substitute key code and meta state for fallback action. 69*38e8c45fSAndroid Build Coastguard Worker struct FallbackAction { 70*38e8c45fSAndroid Build Coastguard Worker int32_t keyCode; 71*38e8c45fSAndroid Build Coastguard Worker int32_t metaState; 72*38e8c45fSAndroid Build Coastguard Worker }; 73*38e8c45fSAndroid Build Coastguard Worker 74*38e8c45fSAndroid Build Coastguard Worker /* Loads a key character map from a file. */ 75*38e8c45fSAndroid Build Coastguard Worker static base::Result<std::unique_ptr<KeyCharacterMap>> load(const std::string& filename, 76*38e8c45fSAndroid Build Coastguard Worker Format format); 77*38e8c45fSAndroid Build Coastguard Worker 78*38e8c45fSAndroid Build Coastguard Worker /* Loads a key character map from its string contents. */ 79*38e8c45fSAndroid Build Coastguard Worker static base::Result<std::shared_ptr<KeyCharacterMap>> loadContents(const std::string& filename, 80*38e8c45fSAndroid Build Coastguard Worker const char* contents, 81*38e8c45fSAndroid Build Coastguard Worker Format format); 82*38e8c45fSAndroid Build Coastguard Worker 83*38e8c45fSAndroid Build Coastguard Worker const std::string getLoadFileName() const; 84*38e8c45fSAndroid Build Coastguard Worker 85*38e8c45fSAndroid Build Coastguard Worker /* Combines this key character map with the provided overlay. */ 86*38e8c45fSAndroid Build Coastguard Worker void combine(const KeyCharacterMap& overlay); 87*38e8c45fSAndroid Build Coastguard Worker 88*38e8c45fSAndroid Build Coastguard Worker /* Clears already applied layout overlay */ 89*38e8c45fSAndroid Build Coastguard Worker void clearLayoutOverlay(); 90*38e8c45fSAndroid Build Coastguard Worker 91*38e8c45fSAndroid Build Coastguard Worker /* Gets the keyboard type. */ 92*38e8c45fSAndroid Build Coastguard Worker KeyboardType getKeyboardType() const; 93*38e8c45fSAndroid Build Coastguard Worker 94*38e8c45fSAndroid Build Coastguard Worker /* Gets the primary character for this key as in the label physically printed on it. 95*38e8c45fSAndroid Build Coastguard Worker * Returns 0 if none (eg. for non-printing keys). */ 96*38e8c45fSAndroid Build Coastguard Worker char16_t getDisplayLabel(int32_t keyCode) const; 97*38e8c45fSAndroid Build Coastguard Worker 98*38e8c45fSAndroid Build Coastguard Worker /* Gets the Unicode character for the number or symbol generated by the key 99*38e8c45fSAndroid Build Coastguard Worker * when the keyboard is used as a dialing pad. 100*38e8c45fSAndroid Build Coastguard Worker * Returns 0 if no number or symbol is generated. 101*38e8c45fSAndroid Build Coastguard Worker */ 102*38e8c45fSAndroid Build Coastguard Worker char16_t getNumber(int32_t keyCode) const; 103*38e8c45fSAndroid Build Coastguard Worker 104*38e8c45fSAndroid Build Coastguard Worker /* Gets the Unicode character generated by the key and meta key modifiers. 105*38e8c45fSAndroid Build Coastguard Worker * Returns 0 if no character is generated. 106*38e8c45fSAndroid Build Coastguard Worker */ 107*38e8c45fSAndroid Build Coastguard Worker char16_t getCharacter(int32_t keyCode, int32_t metaState) const; 108*38e8c45fSAndroid Build Coastguard Worker 109*38e8c45fSAndroid Build Coastguard Worker /* Gets the fallback action to use by default if the application does not 110*38e8c45fSAndroid Build Coastguard Worker * handle the specified key. 111*38e8c45fSAndroid Build Coastguard Worker * Returns true if an action was available, false if none. 112*38e8c45fSAndroid Build Coastguard Worker */ 113*38e8c45fSAndroid Build Coastguard Worker bool getFallbackAction(int32_t keyCode, int32_t metaState, 114*38e8c45fSAndroid Build Coastguard Worker FallbackAction* outFallbackAction) const; 115*38e8c45fSAndroid Build Coastguard Worker 116*38e8c45fSAndroid Build Coastguard Worker /* Gets the first matching Unicode character that can be generated by the key, 117*38e8c45fSAndroid Build Coastguard Worker * preferring the one with the specified meta key modifiers. 118*38e8c45fSAndroid Build Coastguard Worker * Returns 0 if no matching character is generated. 119*38e8c45fSAndroid Build Coastguard Worker */ 120*38e8c45fSAndroid Build Coastguard Worker char16_t getMatch(int32_t keyCode, const char16_t* chars, 121*38e8c45fSAndroid Build Coastguard Worker size_t numChars, int32_t metaState) const; 122*38e8c45fSAndroid Build Coastguard Worker 123*38e8c45fSAndroid Build Coastguard Worker /* Gets a sequence of key events that could plausibly generate the specified 124*38e8c45fSAndroid Build Coastguard Worker * character sequence. Returns false if some of the characters cannot be generated. 125*38e8c45fSAndroid Build Coastguard Worker */ 126*38e8c45fSAndroid Build Coastguard Worker bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, 127*38e8c45fSAndroid Build Coastguard Worker Vector<KeyEvent>& outEvents) const; 128*38e8c45fSAndroid Build Coastguard Worker 129*38e8c45fSAndroid Build Coastguard Worker /* Maps some Android key code to another Android key code. This mapping is applied after 130*38e8c45fSAndroid Build Coastguard Worker * scanCode and usageCodes are mapped to corresponding Android Keycode */ 131*38e8c45fSAndroid Build Coastguard Worker void setKeyRemapping(const std::map<int32_t, int32_t>& keyRemapping); 132*38e8c45fSAndroid Build Coastguard Worker 133*38e8c45fSAndroid Build Coastguard Worker /* Maps a scan code and usage code to a key code, in case this key map overrides 134*38e8c45fSAndroid Build Coastguard Worker * the mapping in some way. */ 135*38e8c45fSAndroid Build Coastguard Worker status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const; 136*38e8c45fSAndroid Build Coastguard Worker 137*38e8c45fSAndroid Build Coastguard Worker /* Returns keycode after applying Android key code remapping defined in mKeyRemapping */ 138*38e8c45fSAndroid Build Coastguard Worker int32_t applyKeyRemapping(int32_t fromKeyCode) const; 139*38e8c45fSAndroid Build Coastguard Worker 140*38e8c45fSAndroid Build Coastguard Worker /** Returns list of keycodes that remap to provided keycode (@see setKeyRemapping()) */ 141*38e8c45fSAndroid Build Coastguard Worker std::vector<int32_t> findKeyCodesMappedToKeyCode(int32_t toKeyCode) const; 142*38e8c45fSAndroid Build Coastguard Worker 143*38e8c45fSAndroid Build Coastguard Worker /* Returns the <keyCode, metaState> pair after applying key behavior defined in the kcm file, 144*38e8c45fSAndroid Build Coastguard Worker * that tries to find a replacement key code based on current meta state */ 145*38e8c45fSAndroid Build Coastguard Worker std::pair<int32_t /*keyCode*/, int32_t /*metaState*/> applyKeyBehavior(int32_t keyCode, 146*38e8c45fSAndroid Build Coastguard Worker int32_t metaState) const; 147*38e8c45fSAndroid Build Coastguard Worker 148*38e8c45fSAndroid Build Coastguard Worker /* Reads a key map from a parcel. */ 149*38e8c45fSAndroid Build Coastguard Worker static std::unique_ptr<KeyCharacterMap> readFromParcel(Parcel* parcel); 150*38e8c45fSAndroid Build Coastguard Worker 151*38e8c45fSAndroid Build Coastguard Worker /* Writes a key map to a parcel. */ 152*38e8c45fSAndroid Build Coastguard Worker void writeToParcel(Parcel* parcel) const; 153*38e8c45fSAndroid Build Coastguard Worker 154*38e8c45fSAndroid Build Coastguard Worker bool operator==(const KeyCharacterMap& other) const = default; 155*38e8c45fSAndroid Build Coastguard Worker 156*38e8c45fSAndroid Build Coastguard Worker KeyCharacterMap(const KeyCharacterMap& other) = default; 157*38e8c45fSAndroid Build Coastguard Worker 158*38e8c45fSAndroid Build Coastguard Worker private: 159*38e8c45fSAndroid Build Coastguard Worker struct Behavior { 160*38e8c45fSAndroid Build Coastguard Worker /* The meta key modifiers for this behavior. */ 161*38e8c45fSAndroid Build Coastguard Worker int32_t metaState = 0; 162*38e8c45fSAndroid Build Coastguard Worker 163*38e8c45fSAndroid Build Coastguard Worker /* The character to insert. */ 164*38e8c45fSAndroid Build Coastguard Worker char16_t character = 0; 165*38e8c45fSAndroid Build Coastguard Worker 166*38e8c45fSAndroid Build Coastguard Worker /* The fallback keycode if the key is not handled. */ 167*38e8c45fSAndroid Build Coastguard Worker int32_t fallbackKeyCode = 0; 168*38e8c45fSAndroid Build Coastguard Worker 169*38e8c45fSAndroid Build Coastguard Worker /* The replacement keycode if the key has to be replaced outright. */ 170*38e8c45fSAndroid Build Coastguard Worker int32_t replacementKeyCode = 0; 171*38e8c45fSAndroid Build Coastguard Worker 172*38e8c45fSAndroid Build Coastguard Worker bool operator==(const Behavior&) const = default; 173*38e8c45fSAndroid Build Coastguard Worker }; 174*38e8c45fSAndroid Build Coastguard Worker 175*38e8c45fSAndroid Build Coastguard Worker struct Key { 176*38e8c45fSAndroid Build Coastguard Worker bool operator==(const Key&) const = default; 177*38e8c45fSAndroid Build Coastguard Worker 178*38e8c45fSAndroid Build Coastguard Worker /* The single character label printed on the key, or 0 if none. */ 179*38e8c45fSAndroid Build Coastguard Worker char16_t label = 0; 180*38e8c45fSAndroid Build Coastguard Worker 181*38e8c45fSAndroid Build Coastguard Worker /* The number or symbol character generated by the key, or 0 if none. */ 182*38e8c45fSAndroid Build Coastguard Worker char16_t number = 0; 183*38e8c45fSAndroid Build Coastguard Worker 184*38e8c45fSAndroid Build Coastguard Worker /* The list of key behaviors sorted from most specific to least specific 185*38e8c45fSAndroid Build Coastguard Worker * meta key binding. */ 186*38e8c45fSAndroid Build Coastguard Worker std::list<Behavior> behaviors; 187*38e8c45fSAndroid Build Coastguard Worker }; 188*38e8c45fSAndroid Build Coastguard Worker 189*38e8c45fSAndroid Build Coastguard Worker class Parser { 190*38e8c45fSAndroid Build Coastguard Worker enum State { 191*38e8c45fSAndroid Build Coastguard Worker STATE_TOP = 0, 192*38e8c45fSAndroid Build Coastguard Worker STATE_KEY = 1, 193*38e8c45fSAndroid Build Coastguard Worker }; 194*38e8c45fSAndroid Build Coastguard Worker 195*38e8c45fSAndroid Build Coastguard Worker enum { 196*38e8c45fSAndroid Build Coastguard Worker PROPERTY_LABEL = 1, 197*38e8c45fSAndroid Build Coastguard Worker PROPERTY_NUMBER = 2, 198*38e8c45fSAndroid Build Coastguard Worker PROPERTY_META = 3, 199*38e8c45fSAndroid Build Coastguard Worker }; 200*38e8c45fSAndroid Build Coastguard Worker 201*38e8c45fSAndroid Build Coastguard Worker struct Property { 202*38e8c45fSAndroid Build Coastguard Worker inline explicit Property(int32_t property = 0, int32_t metaState = 0) : propertyProperty203*38e8c45fSAndroid Build Coastguard Worker property(property), metaState(metaState) { } 204*38e8c45fSAndroid Build Coastguard Worker 205*38e8c45fSAndroid Build Coastguard Worker int32_t property; 206*38e8c45fSAndroid Build Coastguard Worker int32_t metaState; 207*38e8c45fSAndroid Build Coastguard Worker }; 208*38e8c45fSAndroid Build Coastguard Worker 209*38e8c45fSAndroid Build Coastguard Worker KeyCharacterMap* mMap; 210*38e8c45fSAndroid Build Coastguard Worker Tokenizer* mTokenizer; 211*38e8c45fSAndroid Build Coastguard Worker Format mFormat; 212*38e8c45fSAndroid Build Coastguard Worker State mState; 213*38e8c45fSAndroid Build Coastguard Worker int32_t mKeyCode; 214*38e8c45fSAndroid Build Coastguard Worker 215*38e8c45fSAndroid Build Coastguard Worker public: 216*38e8c45fSAndroid Build Coastguard Worker Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format); 217*38e8c45fSAndroid Build Coastguard Worker status_t parse(); 218*38e8c45fSAndroid Build Coastguard Worker 219*38e8c45fSAndroid Build Coastguard Worker private: 220*38e8c45fSAndroid Build Coastguard Worker status_t parseType(); 221*38e8c45fSAndroid Build Coastguard Worker status_t parseMap(); 222*38e8c45fSAndroid Build Coastguard Worker status_t parseMapKey(); 223*38e8c45fSAndroid Build Coastguard Worker status_t parseKey(); 224*38e8c45fSAndroid Build Coastguard Worker status_t parseKeyProperty(); 225*38e8c45fSAndroid Build Coastguard Worker status_t finishKey(Key& key); 226*38e8c45fSAndroid Build Coastguard Worker status_t parseModifier(const std::string& token, int32_t* outMetaState); 227*38e8c45fSAndroid Build Coastguard Worker status_t parseCharacterLiteral(char16_t* outCharacter); 228*38e8c45fSAndroid Build Coastguard Worker }; 229*38e8c45fSAndroid Build Coastguard Worker 230*38e8c45fSAndroid Build Coastguard Worker std::map<int32_t, Key> mKeys; 231*38e8c45fSAndroid Build Coastguard Worker KeyboardType mType = KeyboardType::UNKNOWN; 232*38e8c45fSAndroid Build Coastguard Worker std::string mLoadFileName; 233*38e8c45fSAndroid Build Coastguard Worker bool mLayoutOverlayApplied = false; 234*38e8c45fSAndroid Build Coastguard Worker 235*38e8c45fSAndroid Build Coastguard Worker std::map<int32_t /* fromAndroidKeyCode */, int32_t /* toAndroidKeyCode */> mKeyRemapping; 236*38e8c45fSAndroid Build Coastguard Worker std::map<int32_t /* fromScanCode */, int32_t /* toAndroidKeyCode */> mKeysByScanCode; 237*38e8c45fSAndroid Build Coastguard Worker std::map<int32_t /* fromHidUsageCode */, int32_t /* toAndroidKeyCode */> mKeysByUsageCode; 238*38e8c45fSAndroid Build Coastguard Worker 239*38e8c45fSAndroid Build Coastguard Worker KeyCharacterMap(const std::string& filename); 240*38e8c45fSAndroid Build Coastguard Worker 241*38e8c45fSAndroid Build Coastguard Worker const Key* getKey(int32_t keyCode) const; 242*38e8c45fSAndroid Build Coastguard Worker const Behavior* getKeyBehavior(int32_t keyCode, int32_t metaState) const; 243*38e8c45fSAndroid Build Coastguard Worker static bool matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState); 244*38e8c45fSAndroid Build Coastguard Worker 245*38e8c45fSAndroid Build Coastguard Worker bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const; 246*38e8c45fSAndroid Build Coastguard Worker 247*38e8c45fSAndroid Build Coastguard Worker static void addKey(Vector<KeyEvent>& outEvents, 248*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time); 249*38e8c45fSAndroid Build Coastguard Worker static void addMetaKeys(Vector<KeyEvent>& outEvents, 250*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId, int32_t metaState, bool down, nsecs_t time, 251*38e8c45fSAndroid Build Coastguard Worker int32_t* currentMetaState); 252*38e8c45fSAndroid Build Coastguard Worker static bool addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents, 253*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId, int32_t metaState, bool down, nsecs_t time, 254*38e8c45fSAndroid Build Coastguard Worker int32_t keyCode, int32_t keyMetaState, 255*38e8c45fSAndroid Build Coastguard Worker int32_t* currentMetaState); 256*38e8c45fSAndroid Build Coastguard Worker static void addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents, 257*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId, int32_t metaState, bool down, nsecs_t time, 258*38e8c45fSAndroid Build Coastguard Worker int32_t leftKeyCode, int32_t leftKeyMetaState, 259*38e8c45fSAndroid Build Coastguard Worker int32_t rightKeyCode, int32_t rightKeyMetaState, 260*38e8c45fSAndroid Build Coastguard Worker int32_t eitherKeyMetaState, 261*38e8c45fSAndroid Build Coastguard Worker int32_t* currentMetaState); 262*38e8c45fSAndroid Build Coastguard Worker static void addLockedMetaKey(Vector<KeyEvent>& outEvents, 263*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId, int32_t metaState, nsecs_t time, 264*38e8c45fSAndroid Build Coastguard Worker int32_t keyCode, int32_t keyMetaState, 265*38e8c45fSAndroid Build Coastguard Worker int32_t* currentMetaState); 266*38e8c45fSAndroid Build Coastguard Worker 267*38e8c45fSAndroid Build Coastguard Worker /* Clears all data stored in this key character map */ 268*38e8c45fSAndroid Build Coastguard Worker void clear(); 269*38e8c45fSAndroid Build Coastguard Worker 270*38e8c45fSAndroid Build Coastguard Worker /* Loads the KeyCharacterMap provided by the tokenizer into this instance. */ 271*38e8c45fSAndroid Build Coastguard Worker status_t load(Tokenizer* tokenizer, Format format); 272*38e8c45fSAndroid Build Coastguard Worker 273*38e8c45fSAndroid Build Coastguard Worker /* Reloads the data from mLoadFileName and unapplies any overlay. */ 274*38e8c45fSAndroid Build Coastguard Worker status_t reloadBaseFromFile(); 275*38e8c45fSAndroid Build Coastguard Worker }; 276*38e8c45fSAndroid Build Coastguard Worker 277*38e8c45fSAndroid Build Coastguard Worker } // namespace android 278