Android5.0キーklファイルロードプロセス分析

50852 ワード

以前のキープロセス分析のいくつかのブログでは、キーklファイルのロードについて分析したことがありますが、非常に詳細ではありません.このブログは主にklファイルのロードプロセスを単独で分析しています.
  • InputDeviceIdentifierのnameとDeviceの作成InputDeviceIdentifierのnameを取得することは非常に重要であり、後でidc kl kcmファイルを探すにはこのnameが必要である.次の呼び出しプロセスEventHub::getEvents->EventHub::scanDevicesLocked->EventHub::scanDirLocked->EventHub::openDeviceLocked EventHub::openDeviceLocked関数を見てみましょう.まずdevicePathを開き、ioctlを使用してInputDeviceIdentifierのname
  • を取得します.
    status_t EventHub::openDeviceLocked(const char *devicePath) {  
        char buffer[80];  
    
        ALOGE("Opening device: %s", devicePath);  
    
        int fd = open(devicePath, O_RDWR | O_CLOEXEC);  
        if(fd < 0) {  
            ALOGE("could not open %s, %s
    "
    , devicePath, strerror(errno)); return -1; } InputDeviceIdentifier identifier; // Get device name. if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) { //fprintf(stderr, "could not get device name for %s, %s
    "
    , devicePath, strerror(errno)); } else { buffer[sizeof(buffer) - 1] = '\0'; identifier.name.setTo(buffer); }

    以下にデバイスを作成し、各種印刷を行います.//Load the configuration file for the device. loadConfigurationLocked(device); まず印刷を見てみましょう
    EventHub: Opening device: /dev/input/event4  
    EventHub: Created descriptor: raw=:0000:0000:name:comip_snd_soc Headset, cooked=2efc90e2a7d3beb2de2b795a507e8489f0acd57f  
    EventHub: add device 1: /dev/input/event4  
    EventHub:   bus:        0000  
    EventHub:   vendor      0000  
    EventHub:   product     0000  
    EventHub:   version     0000  
    EventHub:   name:       "comip_snd_soc Headset"  
    EventHub:   location:   "ALSA"  
    EventHub:   unique id:  ""  
    EventHub:   descriptor: "2efc90e2a7d3beb2de2b795a507e8489f0acd57f"  
    EventHub:   driver:     v1.0.1  
    
  • はidcファイルをロードします.私たちのデバイスでは、一般的に自分のidcファイルを定義していないので、見つかりません.一般的にidcファイルを定義し、このファイルでklとkcmファイルを定義します.さらに、loadConfigurationLocked関数を解析し、g e t i n p u t D i c e C o n f i g u r ationFilePathByDeviceIdentifiier関数を呼び出し、configurationFileが空でない場合、PropertyMap::loadを呼び出してidcファイルをロードします.このコードはsystem/libutilの下にあり、このidcファイルがある場合、device->configurationは空ではありません.
  • void EventHub::loadConfigurationLocked(Device* device) {  
        device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(  
                device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);  
        if (device->configurationFile.isEmpty()) {//configurationFile   
            ALOGD("No input device configuration file found for device '%s'.",  
                    device->identifier.name.string());  
        } else {// configurationFile , PropertyMap::load   
            ALOGD("input device configuration file name '%s'.",  
                    device->configurationFile.string());  
            status_t status = PropertyMap::load(device->configurationFile,  
                    &device->configuration);  
            if (status) {  
                ALOGE("Error loading input device configuration file for device '%s'.  "  
                        "Using default configuration.",  
                        device->identifier.name.string());  
            }  
        }  
    }  
     getInputDeviceConfigurationFilePathByDeviceIdentifier , type 0, idc 
    [cpp] view plain copy
    String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(  
            const InputDeviceIdentifier& deviceIdentifier,  
            InputDeviceConfigurationFileType type) {  
        if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {//   
            if (deviceIdentifier.version != 0) {  
                // Try vendor product version.  
                String8 versionPath(getInputDeviceConfigurationFilePathByName(  
                        String8::format("Vendor_%04x_Product_%04x_Version_%04x",  
                                deviceIdentifier.vendor, deviceIdentifier.product,  
                                deviceIdentifier.version),  
                        type));  
                if (!versionPath.isEmpty()) {  
                    return versionPath;  
                }  
            }  
    
            // Try vendor product.  
            String8 productPath(getInputDeviceConfigurationFilePathByName(  
                    String8::format("Vendor_%04x_Product_%04x",  
                            deviceIdentifier.vendor, deviceIdentifier.product),  
                    type));  
            if (!productPath.isEmpty()) {  
                return productPath;  
            }  
        }  
    
        // Try device name.  
        return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);  
    }  

    次に、g e t I n p u t D e v e c e C o n f i g u rationFilePathByName関数を見てみましょう.
    String8 getInputDeviceConfigurationFilePathByName(  
            const String8& name, InputDeviceConfigurationFileType type) {  
        // Search system repository.  
        String8 path;  
        path.setTo(getenv("ANDROID_ROOT"));  
        path.append("/usr/");  
        appendInputDeviceConfigurationFileRelativePath(path, name, type);  
        ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());  
        if (!access(path.string(), R_OK)) {  
            ALOGD("Found");  
            return path;  
        }  
    
        // Search user repository.  
        // TODO Should only look here if not in safe mode.  
        path.setTo(getenv("ANDROID_DATA"));  
        path.append("/system/devices/");  
        appendInputDeviceConfigurationFileRelativePath(path, name, type);  
        ALOGD("Probing for system user input device configuration file: path='%s'", path.string());  
        if (!access(path.string(), R_OK)) {  
            ALOGD("Found");  
            return path;  
        }  
    
        // Not found.  
        ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",  
                name.string(), type);  
        return String8();  
    }  

    この関数は、一致するidcファイルを探して、最後に見つからずに空のStringを返します.A p p p e n d I n p u t D e v i c e C o f i g u rationFileRelativePath関数を見てみましょう
    static void appendInputDeviceConfigurationFileRelativePath(String8& path,  
            const String8& name, InputDeviceConfigurationFileType type) {  
        path.append(CONFIGURATION_FILE_DIR[type]);  
        for (size_t i = 0; i < name.length(); i++) {  
            char ch = name[i];  
            if (!isValidNameChar(ch)) {  
                ch = '_';  
            }  
            path.append(&ch, 1);  
        }  
        path.append(CONFIGURATION_FILE_EXTENSION[type]);  
    }  
    static const char* CONFIGURATION_FILE_DIR[] = {  
            "idc/",  
            "keylayout/",  
            "keychars/",  
    };  
    
    static const char* CONFIGURATION_FILE_EXTENSION[] = {  
            ".idc",  
            ".kl",  
            ".kcm",  
    };  

    この関数は、伝達されたパスと名前でidcファイルを構成します.次にg e t I n p u t D i c e C o n f i g u rationFilePathByNameファイルでappendInputDevice C o f i g u rationFileRelativePathファイルからなるidcファイルがあるかどうかを見て、あればidcを返すファイルパスを見つけて、最後に空のstringを返さなければなりません.私たちのこのロゴを見てみましょう.
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/idc/comip_snd_soc_Headset.idc'  
    InputDevice: Probing for system user input device configuration file: path='/data/system/devices/idc/comip_snd_soc_Headset.idc'  
    InputDevice: Probe failed to find input device configuration file: name='comip_snd_soc Headset', type=0  
    EventHub: No input device configuration file found for device 'comip_snd_soc Headset'.  
     log idc 。
    [plain] view plain copy
    root@lte26007:/system/usr/idc # ls  
    AVRCP.idc  
    qwerty.idc  
    qwerty2.idc  
    

    私たちは私たちの携帯電話のidcディレクトリを見て、すべてオリジナルで、つまりframework/base/dataの下のファイルで、すべてオリジナルで、一致するidcファイルが見つからないに違いありません.idcファイルにこのkl kcmファイルの名前を保存します.次はidcファイル、次はその内容です.keyboard.Layoutはklのファイル名、keyboardを表します.characterMapはkcmのファイル名を表します.
    touch.deviceType = touchScreen  
    touch.orientationAware = 1  
    
    keyboard.layout = qwerty  
    keyboard.characterMap = qwerty  
    keyboard.orientationAware = 1  
    keyboard.builtIn = 1  
    
    cursor.mode = navigation  
    cursor.orientationAware = 1  
  • klファイルをロードklとkcmファイルをロードするのはopenDeviceLocked関数でloadKeyMapLocked関数を呼び出して完了します.では、openDeviceLocked関数を分析し続けます.klファイルをロードするコードについて:
  • status_t keyMapStatus = NAME_NOT_FOUND;  
    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {  
        // Load the keymap for the device.  
        keyMapStatus = loadKeyMapLocked(device);  
    }  

    loadKeyMapLocked関数
    status_t EventHub::loadKeyMapLocked(Device* device) {  
        return device->keyMap.load(device->identifier, device->configuration);  
    }  

    load関数を見てみましょう.前のidcファイルは一致していません.そのため、最初のブランチは直接スキップすることができ、probeKeyMap関数を直接見ることができます.
    status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,  
            const PropertyMap* deviceConfiguration) {  
        // Use the configured key layout if available.  
        if (deviceConfiguration) {  
            String8 keyLayoutName;  
            if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),  
                    keyLayoutName)) {  
                status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);  
                if (status == NAME_NOT_FOUND) {  
                    ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "  
                            "it was not found.",  
                            deviceIdenfifier.name.string(), keyLayoutName.string());  
                }  
            }  
    
            String8 keyCharacterMapName;  
            if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),  
                    keyCharacterMapName)) {  
                status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);  
                if (status == NAME_NOT_FOUND) {  
                    ALOGE("Configuration for keyboard device '%s' requested keyboard character "  
                            "map '%s' but it was not found.",  
                            deviceIdenfifier.name.string(), keyLayoutName.string());  
                }  
            }  
    
            if (isComplete()) {  
                return OK;  
            }  
        }  
    
        // Try searching by device identifier.  
        if (probeKeyMap(deviceIdenfifier, String8::empty())) {  
            return OK;  
        }  
    
        // Fall back on the Generic key map.  
        // TODO Apply some additional heuristics here to figure out what kind of  
        //      generic key map to use (US English, etc.) for typical external keyboards.  
        if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {  
            return OK;  
        }  
    
        // Try the Virtual key map as a last resort.  
        if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {  
            return OK;  
        }  
    
        // Give up!  
        ALOGE("Could not determine key map for device '%s' and no default key maps were found!",  
                deviceIdenfifier.name.string());  
        return NAME_NOT_FOUND;  
    }  

    3.1 InputDeviceIdentifierのnameに一致するklファイルが見つかりません.オリジナルのGenericを使用します.klファイルの1つ目は、InputDeviceIdentifierのnameに一致するklファイルが見つからないことです.この場合、Generalを使用します.klファイルの代わりに.次にprobeKeyMap関数を直接見てみましょう.
    bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,  
            const String8& keyMapName) {  
        if (!haveKeyLayout()) {// kl   
            loadKeyLayout(deviceIdentifier, keyMapName);  
        }  
        if (!haveKeyCharacterMap()) {// kcm   
            loadKeyCharacterMap(deviceIdentifier, keyMapName);  
        }  
        return isComplete();  
    }  

    まずisComplete関数を見てみましょう.klファイルとkcmファイルがあってからtrueを返します.load関数を見てください.isCompleteがtrueを返すと、klとkcmファイルが見つかったので、直接returnします.
    inline bool isComplete() const {  
        return haveKeyLayout() && haveKeyCharacterMap();  
    }  

    次にklファイルをロードするプロセスを見てみましょう.kcmファイルのロードプロセスはklと似ています.私たちは見ません.
    status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,  
            const String8& name) {  
        String8 path(getPath(deviceIdentifier, name,  
                INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));  
        if (path.isEmpty()) {  
            return NAME_NOT_FOUND;  
        }  
        ALOGE("loadKeyLayout path '%s'.",  
                            path.string());  
    
        status_t status = KeyLayoutMap::load(path, &keyLayoutMap);  
        if (status) {  
            return status;  
        }  
    
        keyLayoutFile.setTo(path);  
        return OK;  
    }  

    まずgetPath関数を見てみると、load関数でloadKeyLayoutを呼び出した最初のnameは空なので、ここではg e t I n p u t D e v e C o n f i g u rationFilePathByDeviceIdentifiier関数を使用します.
    String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,  
            const String8& name, InputDeviceConfigurationFileType type) {  
        return name.isEmpty()  
                ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)  
                : getInputDeviceConfigurationFilePathByName(name, type);  
    }  

    g e t I n p u t D i c e C o n f i g u r a t i o n F i l e PathByDeviceIdentifiier関数を見てみると、最初の部分は各種Vendorのようなklで、私たちはこの分岐に入っていません.
    String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(  
            const InputDeviceIdentifier& deviceIdentifier,  
            InputDeviceConfigurationFileType type) {  
        if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {  
            if (deviceIdentifier.version != 0) {  
                // Try vendor product version.  
                String8 versionPath(getInputDeviceConfigurationFilePathByName(  
                        String8::format("Vendor_%04x_Product_%04x_Version_%04x",  
                                deviceIdentifier.vendor, deviceIdentifier.product,  
                                deviceIdentifier.version),  
                        type));  
                if (!versionPath.isEmpty()) {  
                    return versionPath;  
                }  
            }  
    
            // Try vendor product.  
            String8 productPath(getInputDeviceConfigurationFilePathByName(  
                    String8::format("Vendor_%04x_Product_%04x",  
                            deviceIdentifier.vendor, deviceIdentifier.product),  
                    type));  
            if (!productPath.isEmpty()) {  
                return productPath;  
            }  
        }  
    
        // Try device name.  
        return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);  
    }  
     getInputDeviceConfigurationFilePathByName , idc , kl 
    [cpp] view plain copy
    String8 getInputDeviceConfigurationFilePathByName(  
            const String8& name, InputDeviceConfigurationFileType type) {  
        // Search system repository.  
        String8 path;  
        path.setTo(getenv("ANDROID_ROOT"));  
        path.append("/usr/");  
        appendInputDeviceConfigurationFileRelativePath(path, name, type);  
        ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());  
        if (!access(path.string(), R_OK)) {  
            ALOGD("Found");  
            return path;  
        }  
    
        // Search user repository.  
        // TODO Should only look here if not in safe mode.  
        path.setTo(getenv("ANDROID_DATA"));  
        path.append("/system/devices/");  
        appendInputDeviceConfigurationFileRelativePath(path, name, type);  
        ALOGD("Probing for system user input device configuration file: path='%s'", path.string());  
        if (!access(path.string(), R_OK)) {  
            ALOGD("Found");  
            return path;  
        }  
    
        // Not found.  
        ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",  
                name.string(), type);  
        return String8();  
    }  

    以前私たちのロゴでは、このnameがcomipです.snd_soc Headsetも、見つからなかった.
    EventHub:   name:       "comip_snd_soc Headset"  

    デバイスにどのklファイルがあるか見てみましょう.確かにcomipがありません.snd_soc Headsetというファイル.
    AVRCP.kl  
    Generic.kl  
    Vendor_0079_Product_0011.kl  
    Vendor_045e_Product_028e.kl  
    Vendor_046d_Product_b501.kl  
    Vendor_046d_Product_c216.kl  
    Vendor_046d_Product_c219.kl  
    Vendor_046d_Product_c21d.kl  
    Vendor_046d_Product_c21f.kl  
    Vendor_046d_Product_c294.kl  
    Vendor_046d_Product_c299.kl  
    Vendor_046d_Product_c532.kl  
    Vendor_054c_Product_0268.kl  
    Vendor_0583_Product_2060.kl  
    Vendor_05ac_Product_0239.kl  
    Vendor_0b05_Product_4500.kl  
    Vendor_1038_Product_1412.kl  
    Vendor_12bd_Product_d015.kl  
    Vendor_1532_Product_0900.kl  
    Vendor_1689_Product_fd00.kl  
    Vendor_1689_Product_fd01.kl  
    Vendor_1689_Product_fe00.kl  
    Vendor_18d1_Product_2c40.kl  
    Vendor_18d1_Product_5018.kl  
    Vendor_1949_Product_0401.kl  
    Vendor_1bad_Product_f016.kl  
    Vendor_1bad_Product_f023.kl  
    Vendor_1bad_Product_f027.kl  
    Vendor_1bad_Product_f036.kl  
    Vendor_1d79_Product_0009.kl  
    Vendor_22b8_Product_093d.kl  
    Vendor_2378_Product_1008.kl  
    Vendor_2378_Product_100a.kl  
    comip-gpio-keys.kl  
    comip-keypad.kl  
    ft5x06.kl  
    h2w_headset.kl  
    qwerty.kl  
    sensor00fn11.kl  

    振り返ってみるとload関数が呼び出した2番目のprobeKeyMap関数はGenericパラメータに渡されたもので、
    if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {  
        return OK;  
    }  

    probeKeyMap関数を見てみましょうか、loadKeyLayout関数を呼び出しましたか.
    bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,  
            const String8& keyMapName) {  
        if (!haveKeyLayout()) {  
            loadKeyLayout(deviceIdentifier, keyMapName);  
        }  
        if (!haveKeyCharacterMap()) {  
            loadKeyCharacterMap(deviceIdentifier, keyMapName);  
        }  
        return isComplete();  
    }  
    
    status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,  
            const String8& name) {  
        String8 path(getPath(deviceIdentifier, name,  
                INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));  
        if (path.isEmpty()) {  
            return NAME_NOT_FOUND;  
        }  
        ALOGE("kangchen  loadKeyLayout path '%s'.",  
                            path.string());  
    
        status_t status = KeyLayoutMap::load(path, &keyLayoutMap);  
        if (status) {  
            return status;  
        }  
    
        keyLayoutFile.setTo(path);  
        return OK;  
    }  

    同様にgetPath関数を見てみましょう.このときnameは空ではありません.getInputDeviceConfigurationFilePathByName関数を呼び出します.
    String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,  
            const String8& name, InputDeviceConfigurationFileType type) {  
        return name.isEmpty()  
                ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)  
                : getInputDeviceConfigurationFilePathByName(name, type);  
    }  

    G e t I n p u t D i c e C o n f i g u rationFilePathByName関数は、最後にこの関数でGenericを見つけた.klファイル.
    String8 getInputDeviceConfigurationFilePathByName(  
            const String8& name, InputDeviceConfigurationFileType type) {  
        // Search system repository.  
        String8 path;  
        path.setTo(getenv("ANDROID_ROOT"));  
        path.append("/usr/");  
        appendInputDeviceConfigurationFileRelativePath(path, name, type);  
        ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());  
        if (!access(path.string(), R_OK)) {  
            ALOGD("Found");  
            return path;  
        }  
    
        // Search user repository.  
        // TODO Should only look here if not in safe mode.  
        path.setTo(getenv("ANDROID_DATA"));  
        path.append("/system/devices/");  
        appendInputDeviceConfigurationFileRelativePath(path, name, type);  
        ALOGD("Probing for system user input device configuration file: path='%s'", path.string());  
        if (!access(path.string(), R_OK)) {  
            ALOGD("Found");  
            return path;  
        }  
    
        // Not found.  
        ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",  
                name.string(), type);  
        return String8();  
    }  

    klファイルを見つけたら、このファイルをload関数で解析します.これは分析しません.スキャンコードをキーコードに変換するなどです.
    status_t KeyLayoutMap::load(const String8& filename, sp* outMap) {  
        outMap->clear();  
    
        Tokenizer* tokenizer;  
        status_t status = Tokenizer::open(filename, &tokenizer);  
        if (status) {  
            ALOGE("Error %d opening key layout map file %s.", status, filename.string());  
        } else {  
            sp map = new KeyLayoutMap();  
            if (!map.get()) {  
                ALOGE("Error allocating key layout map.");  
                status = NO_MEMORY;  
            } else {  
    #if DEBUG_PARSER_PERFORMANCE  
                nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);  
    #endif  
                Parser parser(map.get(), tokenizer);  
                status = parser.parse();  
    #if DEBUG_PARSER_PERFORMANCE  
                nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;  
                ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.",  
                        tokenizer->getFilename().string(), tokenizer->getLineNumber(),  
                        elapsedTime / 1000000.0);  
    #endif  
                if (!status) {  
                    *outMap = map;  
                }  
            }  
            delete tokenizer;  
        }  
        return status;  
    }  
     , 。
    [plain] view plain copy
    key 113   VOLUME_MUTE  
    key 114   VOLUME_DOWN  
    key 115   VOLUME_UP  
    key 116   POWER  
     kl 。 log
    [plain] view plain copy
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keylayout/comip_snd_soc_Headset.kl'  
    InputDevice: Probing for system user input device configuration file: path='/data/system/devices/keylayout/comip_snd_soc_Headset.kl'  
    InputDevice: Probe failed to find input device configuration file: name='comip_snd_soc Headset', type=1  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keychars/comip_snd_soc_Headset.kcm'  
    InputDevice: Probing for system user input device configuration file: path='/data/system/devices/keychars/comip_snd_soc_Headset.kcm'  
    InputDevice: Probe failed to find input device configuration file: name='comip_snd_soc Headset', type=2  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keylayout/Generic.kl'  
    InputDevice: Found  
    Keyboard: loadKeyLayout path '/system/usr/keylayout/Generic.kl'.  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keychars/Generic.kcm'  
    InputDevice: Found  
    EventHub: Unable to disable kernel key repeat for /dev/input/event4: Function not implemented  
    EventHub: New device: id=1, fd=70, path='/dev/input/event4', name='comip_snd_soc Headset', classes=0x81, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false, wakeMechanism=EPOLLWAKEUP, usingClockIoctl=true  

    上の例はGenericがロードする.klファイルは、system/usr/keylayoutの下に適切なものが見つからないためです.
    3.2 InputDeviceIdentifierに一致するnameを見つけたklファイルの次の例は適切なklファイルを見つけたもので、logを見てみましょう.nameはft 5 x 06であることに注意してください.
    EventHub: Opening device: /dev/input/event3  
    EventHub: Created descriptor: raw=:0000:0000:name:ft5x06, cooked=f2706364e2849110ed562db0c53423b5027a6cc5  
    EventHub: add device 2: /dev/input/event3  
    EventHub:   bus:        0000  
    EventHub:   vendor      0000  
    EventHub:   product     0000  
    EventHub:   version     0000  
    EventHub:   name:       "ft5x06"  
    EventHub:   location:   ""  
    EventHub:   unique id:  ""  
    EventHub:   descriptor: "f2706364e2849110ed562db0c53423b5027a6cc5"  
    EventHub:   driver:     v1.0.1  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/idc/ft5x06.idc'  
    InputDevice: Probing for system user input device configuration file: path='/data/system/devices/idc/ft5x06.idc'  
    InputDevice: Probe failed to find input device configuration file: name='ft5x06', type=0  
    EventHub: No input device configuration file found for device 'ft5x06'.  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keylayout/ft5x06.kl'  
    InputDevice: Found  
    Keyboard: loadKeyLayout path '/system/usr/keylayout/ft5x06.kl'.  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keychars/ft5x06.kcm'  
    InputDevice: Probing for system user input device configuration file: path='/data/system/devices/keychars/ft5x06.kcm'  
    InputDevice: Probe failed to find input device configuration file: name='ft5x06', type=2  
    InputDevice: Probing for system provided input device configuration file: path='/system/usr/keychars/Generic.kcm'  
    InputDevice: Found  
    EventHub: Unable to disable kernel key repeat for /dev/input/event3: Function not implemented  
    EventHub: New device: id=2, fd=71, path='/dev/input/event3', name='ft5x06', classes=0x15, configuration='', keyLayout='/system/usr/keylayout/ft5x06.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false, wakeMechanism=EPOLLWAKEUP, usingClockIoctl=true  

    デバイスのklファイルを見てみましょう.ft 5 x 06があります.klファイル、これで一致するklファイルが見つかり、元のGenericではありません.klです.
    AVRCP.kl  
    Generic.kl  
    Vendor_0079_Product_0011.kl  
    Vendor_045e_Product_028e.kl  
    Vendor_046d_Product_b501.kl  
    Vendor_046d_Product_c216.kl  
    Vendor_046d_Product_c219.kl  
    Vendor_046d_Product_c21d.kl  
    Vendor_046d_Product_c21f.kl  
    Vendor_046d_Product_c294.kl  
    Vendor_046d_Product_c299.kl  
    Vendor_046d_Product_c532.kl  
    Vendor_054c_Product_0268.kl  
    Vendor_0583_Product_2060.kl  
    Vendor_05ac_Product_0239.kl  
    Vendor_0b05_Product_4500.kl  
    Vendor_1038_Product_1412.kl  
    Vendor_12bd_Product_d015.kl  
    Vendor_1532_Product_0900.kl  
    Vendor_1689_Product_fd00.kl  
    Vendor_1689_Product_fd01.kl  
    Vendor_1689_Product_fe00.kl  
    Vendor_18d1_Product_2c40.kl  
    Vendor_18d1_Product_5018.kl  
    Vendor_1949_Product_0401.kl  
    Vendor_1bad_Product_f016.kl  
    Vendor_1bad_Product_f023.kl  
    Vendor_1bad_Product_f027.kl  
    Vendor_1bad_Product_f036.kl  
    Vendor_1d79_Product_0009.kl  
    Vendor_22b8_Product_093d.kl  
    Vendor_2378_Product_1008.kl  
    Vendor_2378_Product_100a.kl  
    comip-gpio-keys.kl  
    comip-keypad.kl  
    ft5x06.kl  
    h2w_headset.kl  
    qwerty.kl  
    sensor00fn11.kl  
  • klファイルを使用して、スキャンコードをキーコードに変換します.以前はキーフロー(一)で、キーを最後に各InputMapperのprocess関数で処理することを説明しました.次に、この関数を見て、EventHubのmapKeyを呼び出してスキャンコードをキーコードに変換します.
  • void KeyboardInputMapper::process(const RawEvent* rawEvent) {  
        switch (rawEvent->type) {  
    
        case EV_KEY: {  
            int32_t scanCode = rawEvent->code;  
            int32_t usageCode = mCurrentHidUsage;  
            mCurrentHidUsage = 0;  
    
            if (isKeyboardOrGamepadKey(scanCode)) {  
                int32_t keyCode;  
                uint32_t flags;  
                if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {//   
                    keyCode = AKEYCODE_UNKNOWN;  
                    flags = 0;  
                }  
                processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);  
            }  
            break;  
        }  
        case EV_MSC: {  
            if (rawEvent->code == MSC_SCAN) {  
                mCurrentHidUsage = rawEvent->value;  
            }  
            break;  
        }  
        case EV_SYN: {  
            if (rawEvent->code == SYN_REPORT) {  
                mCurrentHidUsage = 0;  
            }  
        }  
        }  
    }  
     processKey , InputDispatch 。 。
     mapKey , kcm, kl 。
    [cpp] view plain copy
    status_t EventHub::mapKey(int32_t deviceId,  
            int32_t scanCode, int32_t usageCode, int32_t metaState,  
            int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {  
        AutoMutex _l(mLock);  
        Device* device = getDeviceLocked(deviceId);  
        status_t status = NAME_NOT_FOUND;  
    
        if (device) {  
            // Check the key character map first.  
            sp kcm = device->getKeyCharacterMap();  
            if (kcm != NULL) {  
                if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {  
                    *outFlags = 0;  
                    status = NO_ERROR;  
                }  
            }  
    
            // Check the key layout next.  
            if (status != NO_ERROR && device->keyMap.haveKeyLayout()) {  
                if (!device->keyMap.keyLayoutMap->mapKey(  
                        scanCode, usageCode, outKeycode, outFlags)) {  
                    status = NO_ERROR;  
                }  
            }  
    
            if (status == NO_ERROR) {  
                if (kcm != NULL) {  
                    kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState);  
                } else {  
                    *outMetaState = metaState;  
                }  
            }  
        }  
    
        if (status != NO_ERROR) {  
            *outKeycode = 0;  
            *outFlags = 0;  
            *outMetaState = metaState;  
        }  
    
        return status;  
    }  

    詳しくkcmのmapKeyとklのmapKeyを分析して後で分析しました