Input系统分析详解-InputReader

关键字的理解

下面是在分析的过程中遇到的一些关键字,应该可以更好的帮助读者理解。
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS /
#define EV_SYN 0x00 同步事件
#define EV_KEY 0x01 按键事件
#define EV_REL 0x02 相对坐标
#define EV_ABS 0x03 绝对坐标
/
WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS /
#define EV_MSC 0x04 其它
#define EV_SW 0x05
#define EV_LED 0x11 LED
#define EV_SND 0x12 声音
/
WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define EV_REP 0x14 Repeat
#define EV_FF 0x15 力反馈
#define EV_PWR 0x16 电源
#define EV_FF_STATUS 0x17 状态

InputReader事件处理时序图

在这里插入图片描述

InputReader事件处理分析

从事件系统初始化一章可以知道,InputReaderThread启动之后会调用threadLoop,当返回true会一直循环。

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;
    { // acquire lock
        AutoMutex _l(mLock);

        oldGeneration = mGeneration;
        timeoutMillis = -1;

        uint32_t changes = mConfigurationChangesToRefresh;
        if (changes) {
            mConfigurationChangesToRefresh = 0;
            timeoutMillis = 0;
			//刷新配置
            refreshConfigurationLocked(changes);
        } else if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
        }
    } // release lock
    
	//返回事件个数
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);//当有需要处理的事件时一定要枷锁,将本次上报事件处理完毕后再继续获取事件。
        mReaderIsAliveCondition.broadcast();
		
        if (count) {
			//开始处理事件
            processEventsLocked(mEventBuffer, count);
        }

        if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
                mNextTimeout = LLONG_MAX;
                timeoutExpiredLocked(now);
            }
        }

		//设备是否变化,若是变化则获取输入设备
        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
		//通知上层设备已经发生变化,mPolicy的实现是在com_android_server_input_InputManagerService.cpp中
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }

    // Flush queued events out to the listener.
    // This must happen outside of the lock because the listener could potentially call
    // back into the InputReader's methods, such as getScanCodeState, or become blocked
    // on another thread similarly waiting to acquire the InputReader lock thereby
    // resulting in a deadlock.  This situation is actually quite plausible because the
    // listener is actually the input dispatcher, which calls into the window manager,
    // which occasionally calls into the input reader.
    //通知InputDispatcher,事件到来了,赶紧吃吧
    mQueuedListener->flush();
}

接下来主要分析对通过EvengHub读取的事件进一步处理了。

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
		//此处判断是为了甄别设备是否增删或增删完成操作类型,不是才会执行此逻辑;否则执行else
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
				//此处判断和上面基本相同。
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
			//处理设备事件
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
			//处理设备的增删扫描事件或增删事件的完成
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
				//此处主要是把EventHub中的Device转化为InputReader的InputDevice
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::FINISHED_DEVICE_SCAN:
                handleConfigurationChangedLocked(rawEvent->when);
                break;
            default:
                ALOG_ASSERT(false); // can't happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
	//此处用于判断输入设备是否已经加载
    if (deviceIndex < 0) {
        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
        return;
    }

    InputDevice* device = mDevices.valueAt(deviceIndex);
	//此设备是否有对应的Mapper(Mapper相当与事件的加工厂,如果没有处理的工厂就不需要继续进行下去了)
    if (device->isIgnored()) {
        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }
	//屏蔽掉无用的事件就可以处理了
    device->process(rawEvents, count);
}

//其实下面的很简单,就是把RawEvent交给每个InputMapper进行加工,然后将加工好的事件交给InputDispatcher
//进行分发处理。

void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    // Process all of the events in order for each mapper.
    // We cannot simply ask each mapper to process them in bulk because mappers may
    // have side-effects that must be interleaved.  For example, joystick movement events and
    // gamepad button presses are handled by different mappers but they should be dispatched
    // in the order received.
    size_t numMappers = mMappers.size();
	......
        } else {
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                mapper->process(rawEvent);
            }
        }
    }
}

每个InputMapper加工厂对事件的加工在这里就不介绍了,有兴趣的可以自行研究。
至于InputReader怎么把加工的事件通知到InputDispatcher的,上面的时序图大家可以基本上了解到。其实通知的关键代码如下:

getListener()->notify***(&args);

好了,InputReader就写道这了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞_哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值