Android InputFlinger简单分析(主要分析Touch)

Android InputFlinger简单分析(主要分析Touch)

首先,它有个服务,InputManagerService.

InputManagerService启动

startOtherServices@SystemServer

...
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
     mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
...
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
...
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            inputManager.start();
...

看看构造函数:

public InputManagerService(Context context) {
    ...
    mPtr = nativeInit(this, mContext,mHandler.getLooper().getQueue());
    ...
}

这个mPrt之后作为了其他native函数的第一个参数。先看看nativeInit

(位置base/services/core/jni/com_android_server_input_InputManagerService.cpp)

static jlong nativeInit(JNIEnv* env, jclass clazz,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
    NativeInputManager* im = new NativeInputManager(contextObj,         serviceObj,messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

简单来理解就是获取java层的消息队列,然后构造了一个NativeInputManager对象,然后返回java层,赋值给mPtr。

前文,startOtherServices@SystemServer中还调用了

inputManager.start();

start()@InputManagerService

...
nativeStart(mPtr);
...

nativeStart:

static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();
...
}

即用nativeInit中new的NativeInputManager对象调用start函数。

那NativeInputManager是什么呢?

inline sp<InputManager> getInputManager() const { return mInputManager; }

直接去看InputManager调用start函数就好了。

接下来,我们的工作目录就集中到

frameworks/native/services/inputflinger

从InputManager::start开始

...
  status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
...
  result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
...

mDispatcherThread和mReaderThread的run函数,都会去调用threadLoop函数(就当是常识了)。

bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

从名字上来看,一个专门去读取input,一个专门去分发input.可是为什么只运行一次(loopOnce)呢?

我们这次主要关注的是touch事件,即MotionEvent.

InputDispatcher.h

struct MotionEntry : EventEntry {

Motion是Event的一种!

virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
virtual void notifyKey(const NotifyKeyArgs* args);
virtual void notifyMotion(const NotifyMotionArgs* args);
virtual void notifySwitch(const NotifySwitchArgs* args);
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);

这几个函数功能应该类似,只不过Event种类不同。

在InputDispatcher.cpp中竟然找不到调用。嗯!yes!搜索结果如下:

InputReader.cpp:2551:        getListener()->notifyMotion(&args);
...

getListener@InputReader:

class InputReader : public InputReaderInterface {
...
virtual InputListenerInterface* getListener();

InputDispatcher.h:

class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface
...
class InputDispatcher : public InputDispatcherInterface

回头过去看一下InputManager的构造函数,就都明白了

InputManager::InputManager

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    //注意第三个参数
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

InputReader的构造函数:

InputReader::InputReader(const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        //这个
        const sp<InputListenerInterface>& listener) :
        mContext(this), mEventHub(eventHub), mPolicy(policy),
        mGlobalMetaState(0), mGeneration(1),
        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);

InputListenerInterface* InputReader::ContextImpl::getListener() {
    return mReader->mQueuedListener.get();
}

总的来说就是,notifyMotion函数的调用来自InputReader.读到input之后notify!

InputReader分析

InputReader::loopOnce

//引出一个EventHub,getEvents也非常类似平时在adb shell中使用的命令
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
...
processEventsLocked(mEventBuffer, count);
...

InputReader::processEventsLocked

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
      ...
        //type不是
        //DEVICE_ADDED,DEVICE_REMOVED,FINISHED_DEVICE_SCAN这三个
        if(type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
      ...
        processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        }
    }
}

我们来看看一个开机加载T

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值