Android6.0 按键kl文件加载过程分析

在之前按键过程分析的几篇博客中,我分析过关于按键kl文件的加载,但是讲的不是非常详细,这篇博客主要把kl文件加载过程单独拉出来分析下。

 

1. 获取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\n", 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\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.name.setTo(buffer);
    }

下面创建了Device,各种打印。

    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);

    ALOGW("add device %d: %s\n", deviceId, devicePath); 
    ALOGW("  bus:        %04x\n"
         "  vendor      %04x\n"
         "  product     %04x\n"
         "  version     %04x\n",
        identifier.bus, identifier.vendor, identifier.product, identifier.version);
    ALOGW("  name:       \"%s\"\n", identifier.name.string());
    ALOGW("  location:   \"%s\"\n", identifier.location.string());
    ALOGW("  unique id:  \"%s\"\n", identifier.uniqueId.string());
    ALOGW("  descriptor: \"%s\"\n", identifier.descriptor.string());
    ALOGW("  driver:     v%d.%d.%d\n",
        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);

    // 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

 

2. 加载idc文件

在我们的设备中,一般没有定义自己的idc文件,也就找不到。一般定义idc文件,是在这个文件中定义kl 和kcm文件。

我们再来分析下loadConfigurationLocked函数,调用getInputDeviceConfigurationFilePathByDeviceIdentifier函数,当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文件

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函数:

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.s
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值