android input系统如何导入kl文件

首先在size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize)里有个


 if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
ALOGE("matt-mNeedToScanDevices");
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }//每次新的input设备加入的时候就会调用这个函数


void EventHub::scanDevicesLocked() {
    status_t res = scanDirLocked(DEVICE_PATH);
    if(res < 0) {
        ALOGE("scan dir failed for %s\n", DEVICE_PATH);
    }
    if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
        createVirtualKeyboardLocked();
    }
}


进入status_t EventHub::scanDirLocked(const char *dirname)
{
    char devname[PATH_MAX];
    char *filename;
    DIR *dir;
    struct dirent *de;
    dir = opendir(dirname);
    if(dir == NULL)
        return -1;
    strcpy(devname, dirname);
    filename = devname + strlen(devname);
    *filename++ = '/';
    while((de = readdir(dir))) {
        if(de->d_name[0] == '.' &&
           (de->d_name[1] == '\0' ||
            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        strcpy(filename, de->d_name);
        openDeviceLocked(devname);
    }
    closedir(dir);
    return 0;
}
再进入
status_t EventHub::openDeviceLocked(const char *devicePath)
里头有一句话 loadConfigurationLocked(device);

status_t EventHub::openDeviceLocked(const char *devicePath) {
     ......
    int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier); 
    //先获取device
    //对于touchscren来说device->identifier.name就是ft5x06_ts


   // Load the configuration file for the device.
    loadConfigurationLocked(device); //获取对应的idc文件
   .....


     if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
        // Load the keymap for the device.
          ALOGE("matt-keyMapStatus = loadKeyMapLocked(device)");
        keyMapStatus = loadKeyMapLocked(device);   //获取对应的kl文件
    }
}


接着到void EventHub::loadConfigurationLocked(Device* device) {


    device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
            device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION); 


   //INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION是个type类型
   //这个类型的结构体在
   //enum InputDeviceConfigurationFileType {
    INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0,     /* .idc file */
    INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1,        /* .kl file */
    INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */
};
  // 所以一开始会尝试去找idc文件


   status_t status = PropertyMap::load(device->configurationFile,  //如果返回的路径不是空值则调用load
                &device->configuration);


 }


接着看String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
        const InputDeviceIdentifier& deviceIdentifier,
        InputDeviceConfigurationFileType type) {
      .....
     ALOGE("matt-getInputDeviceConfigurationFilePathByDeviceIdentifier");
    if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
        if (deviceIdentifier.version != 0) {
            // Try vendor product version.
            ALOGE("matt-1");
            String8 versionPath(getInputDeviceConfigurationFilePathByName(
                    String8::format("Vendor_%04x_Product_%04x_Version_%04x",
                            deviceIdentifier.vendor, deviceIdentifier.product,
                            deviceIdentifier.version),
                    type));
            if (!versionPath.isEmpty()) {
                return versionPath;
            }
        }
ALOGE("matt-2");


        // Try vendor product.
        String8 productPath(getInputDeviceConfigurationFilePathByName(
                String8::format("Vendor_%04x_Product_%04x",
                        deviceIdentifier.vendor, deviceIdentifier.product),
                type));
        if (!productPath.isEmpty()) {
            return productPath;
        }
    }
ALOGE("matt-3=%s",deviceIdentifier.name.string());


    // Try device name.
    return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
    //touchscreen直接走最下面的getInputDeviceConfigurationFilePathByName
}


到tring8 getInputDeviceConfigurationFilePathByName(
        const String8& name, InputDeviceConfigurationFileType type) {
    // Search system repository.
    String8 path;
ALOGE("matt-getInputDeviceConfigurationFilePathByName");
    path.setTo(getenv("ANDROID_ROOT"));
    path.append("/usr/");
    appendInputDeviceConfigurationFileRelativePath(path, name, type);


ALOGE("matt-path1=%s",path.string());


 if (!access(path.string(), R_OK)) {
        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);
  ALOGE("matt-path2=%s",path.string());


    if (!access(path.string(), R_OK)) {


        return path;
    }




    return String8();  //如果拼凑出来的路径不可用则直接返回空值  由于第一次进来找的是idc文件而我们只放了kl文件所以返回为0
}




回头看keyMapStatus = loadKeyMapLocked(device)




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






status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
        const PropertyMap* deviceConfiguration) {


// Try searching by device identifier.
    if (probeKeyMap(deviceIdenfifier, String8::empty())) {  //获取kl文件
        return OK;
    }


     if (!haveKeyCharacterMap()) {
        loadKeyCharacterMap(deviceIdentifier, keyMapName); //获取kcm文件原理与上面相同
    }
}


看bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
        const String8& keyMapName) {
    if (!haveKeyLayout()) {
        loadKeyLayout(deviceIdentifier, keyMapName);
    }


 }


继续status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
        const String8& name) {
        ALOGE("matt-loadKeyLayout 1");
    String8 path(getPath(deviceIdentifier, name,INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
   //这里的
}


继续String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
        const String8& name, InputDeviceConfigurationFileType type) {
    return name.isEmpty()
            ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
            : getInputDeviceConfigurationFilePathByName(name, type);
}
这里跑的是getInputDeviceConfigurationFilePathByName,之后

最后都是跑到了
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;

}


static void appendInputDeviceConfigurationFileRelativePath(String8& path,   //这里组成了path
        const String8& name, InputDeviceConfigurationFileType type) {
    path.append(CONFIGURATION_FILE_DIR[type]);   //这里选了文件夹"idc/", "keylayout/",   "keychars/",
    for (size_t i = 0; i < name.length(); i++) {
        char ch = name[i];
        if (!isValidNameChar(ch)) {
            ch = '_';
        }
        path.append(&ch, 1);   //把ft5x06_ts加到/system/usr/keylayout/之后
    }
    path.append(CONFIGURATION_FILE_EXTENSION[type]);//根据type加kl或者kcm或者idc
}



你可能感兴趣的:(android)