Android输入系统之启动篇(AndroidV)

一:概述

    Android是由事件驱动的,当用户点击屏幕时,首先TP驱动识别到点击屏幕点击事件,写入"dev/input"节点,输入系统识别到"dev/input"有新的事件,会把事件进行封装,传递给对应的View进行事件处理。由此可见,事件的获取、传递、分发都是由输入系统来完成,输入系统的重要性不言而喻。下面根据AndroidV的代码来剖析输入系统。

二:输入系统简介

  Input系统中很重要的几个类:InputManagerService、InputReader、InputDispatcher

    InputManagerService和WMS交互,WMS记录所有窗口信息同步到IMS,IMS同步信息到Native,让InputDispatcher可以正确派发input事件到对应窗口。

    InputReader从EventHub中取出input事件并封装,再把事件传递给InputDispatcher。

    InputDispatcher接收InputReader传递过来的input事件,结合IMS传递过来的窗口信息,派发事件到合适的窗口。

Input系统相关的动态库:

    libinputflinger.so:frameworks/native/services/inputflinger/
    libinputservice.so:frameworks/base/libs/input/
    libinput.so: frameworks/native/libs/input/

Input系统相关代码:

frameworks/native/services/inputflinger/
  - InputDispatcher.cpp
  - InputReader.cpp
  - InputManager.cpp
  - EventHub.cpp
  - InputListener.cpp

frameworks/native/libs/input/
  - InputTransport.cpp
  - Input.cpp
  - InputDevice.cpp
  - Keyboard.cpp
  - KeyCharacterMap.cpp
  - IInputConstants.aidl

frameworks/base/services/core/
  - java/com/android/server/input/InputManagerService.java
  - jni/com_android_server_input_InputManagerService.cpp

三:输入系统初始化

    输入系统初始化的入口是InputManagerService(IMS),下面来从IMS的初始化流程解析Input系统的初始化流程

  3.1 SystemServer.startOtherServices

    IMS是系统服务,和AMS、WMS等一样,都是在SystemServer中进行初始化操作的

//frameworks/base/services/java/com/android/server/SystemServer.java
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        ...
        InputManagerService inputManager = null;
        ...
        try {
            ...
            t.traceBegin("StartInputManagerService");
            //初始化IMS
            inputManager = new InputManagerService(context);
            t.traceEnd();
            ...
            //把IMS加入到ServiceManager中,这样其他地方就可以用过Context.INPUT_SERVICE获取到IMS这个系统服务
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            ...
            t.traceBegin("StartInputManager");
            //把InputManagerCallback对象保存到IMS里
            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            //启动IMS
            inputManager.start();
            t.traceEnd();
            ...
        } catch (Throwable e) {...}
        ...
    }

3.2 NativeInputManagerService.NativeImpl.init

    IMS运行在"android.display"线程中,调用Native层的init函数来继续初始化流程

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    public InputManagerService(Context context) {
        //IMS运行在"android.display"线程中
        this(new Injector(context, DisplayThread.get().getLooper()));
    }

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    InputManagerService(Injector injector) {
        ...
        //获取NativeInputManagerService对象
        mNative = injector.getNativeService(this);
        ...
    }

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    static class Injector {
        NativeInputManagerService getNativeService(InputManagerService service) {
            //初始化NativeImpl
            return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
        }
    }

//frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java
    class NativeImpl implements NativeInputManagerService {
        NativeImpl(InputManagerService service, MessageQueue messageQueue) {
            mPtr = init(service, messageQueue);
        }

        private native long init(InputManagerService service, MessageQueue messageQueue);
    }

3.3 com_android_server_input_InputManagerService.nativeInit

    通过jni来初始化InputManager对象

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj,
                        jobject messageQueueObj) {
    //获取native消息队列
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    ...
    std::call_once(nativeInitialize, [&]() {
        //初始化NativeInputManager
        im = new NativeInputManager(serviceObj, messageQueue->getLooper());
    });
    //返回native对象指针
    return reinterpret_cast<jlong>(im);
}

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject serviceObj, const sp<Looper>& looper)
      : mLooper(looper), mInteractive(true) {
    ...
    //初始化InputManager
    InputManager* im = new InputManager(this, *this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

3.4 InputManager.InputManager

    在InputManager的构造函数中创建InputDispatcher和InputReader对象

//frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
                           InputDispatcherPolicyInterface& dispatcherPolicy) {
    //创建InputDispatcher
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    ...
    //创建InputReader,这里的*mBlocker就是InputDispatcher
    mReader = createInputReader(readerPolicy, *mBlocker);
}

3.5 InputDispatcher.InputDispatcher

    在InputDispatcher构造函数中完成创建InputReporter对象、初始化DispatcherWindowListener对象,用于监听窗口焦点变化、添加DispatcherWindowListener监听器等工作

//frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
std::unique_ptr<InputDispatcherInterface> createInputDispatcher(
        InputDispatcherPolicyInterface& policy) {
    return std::make_unique<android::inputdispatcher::InputDispatcher>(policy);
}

//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
                                 std::chrono::nanoseconds staleEventTimeout)
      : mPolicy(policy),
        mPendingEvent(nullptr),
        mLastDropReason(DropReason::NOT_DROPPED),
        mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
        mAppSwitchSawKeyDown(false),
        mAppSwitchDueTime(LLONG_MAX),
        mNextUnblockedEvent(nullptr),
        //设置分发超时时间
        mMonitorDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT),
        mDispatchEnabled(false),
        mDispatchFrozen(false),
        mInputFilterEnabled(false),
        mMaximumObscuringOpacityForTouch(1.0f),
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
        mWindowTokenWithPointerCapture(nullptr),
        mStaleEventTimeout(staleEventTimeout),
        mLatencyAggregator(),
        mLatencyTracker(&mLatencyAggregator) {
    ...
    mLooper = sp<Looper>::make(false);
    //创建InputReporter对象
    mReporter = createInputReporter();
    //初始化DispatcherWindowListener对象,用于监听窗口焦点变化
    mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
#if defined(__ANDROID__)
    //添加DispatcherWindowListener监听器
    SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener);
#endif
    ...
}

3.6 InputReaderFactory.createInputReader

    先创建EventHub对象然后作为参数创建InputReader对象

//frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
std::unique_ptr<InputReaderInterface> createInputReader(
        const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
    return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
}

3.7 EventHub.EventHub

   EventHub在构造函数中主要完成了以下两个工作

  •     初始化INotify(监听”/dev/input”),并添加到epoll实例
  •     创建非阻塞模式的管道,并添加到epoll;
//frameworks/native/services/inputflinger/reader/EventHub.cpp
EventHub::EventHub(void)
      : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
        mNextDeviceId(1),
        mControllerNumbers(),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false),
        mNeedToScanDevices(true),
        mPendingEventCount(0),
        mPendingEventIndex(0),
        mPendingINotify(false) {
    ensureProcessCanBlockSuspend();
    //创建epoll
    mEpollFd = epoll_create1(EPOLL_CLOEXEC);

    mINotifyFd = inotify_init1(IN_CLOEXEC);

    std::error_code errorCode;
    bool isDeviceInotifyAdded = false;
    if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
        //添加设备监听
        addDeviceInputInotify();
    } else {
        ...
    }
    ...
    //添加mINotifyFd到epoll实例
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);

    int wakeFds[2];
    //创建管道
    result = pipe2(wakeFds, O_CLOEXEC);

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];
    //将pipe的读设置为非阻塞方式
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    //将pipe的写设置为非阻塞方式
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);

    eventItem.data.fd = mWakeReadPipeFd;
    //添加管道的读端到epoll实例
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}

//frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::addDeviceInputInotify() {
    //监听"input/dev"路径下设备
    mDeviceInputWd = inotify_add_watch(mINotifyFd, DEVICE_INPUT_PATH, IN_DELETE | IN_CREATE);
}

3.8 InputReader.InputReader

//frameworks/native/services/inputflinger/reader/InputReader.cpp
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         InputListenerInterface& listener)
      : mContext(this),
        mEventHub(eventHub),
        mPolicy(policy),
        //创建输入对象
        mQueuedListener(listener),
        mGlobalMetaState(AMETA_NONE),
        mLedMetaState(AMETA_NONE),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    refreshConfigurationLocked(/*changes=*/{});
    updateGlobalMetaStateLocked();
}

至此,Input系统的初始化流程完毕。

四:输入系统启动

  Input系统完成初始化流程后,是如何启动的呢?回看3.1章节,在IMS初始化完成后,会调用IMS.start来进行启动流程。启动流程比较简单,主要做了以下两件事情

  • 启动"InputDispatcher"线程,来接收InputReader传过来的input事件
  • 启动"InputReader"线程,来循环读取input事件
//frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java
    class NativeImpl implements NativeInputManagerService {
        @Override
        public native void start();

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);

    status_t result = im->getInputManager()->start();
    ...
}

//frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
    //启动InputDispatcher
    status_t result = mDispatcher->start();
    ...
    //启动InputReader
    result = mReader->start();
    ...
}

//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::start() {
    //启动"InputDispatcher"线程,来接收InputReader传过来的input事件
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

//frameworks/native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {
    //启动"InputReader"线程,来循环读取input事件
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
    return OK;
}

五:小结

    从上述启动流程可以看出来,主要有三个线程和Input系统息息相关。IMS所在的"android.display"线程,InputDispatcher所在的"InputDispatcher"线程以及InputReader所在的"InputReader"线程。

    "android.display"线程:属于Looper线程,用于处理Java层的IMS.InputManagerHandler和JNI层的NativeInputManager中指定的MessageHandler消息。

    "InputDispatcher"线程:属于Looper线程,循环发送消息。

    "InputReader"现成:通过EventHub的getEvents函数不断读取事件,然后进行封装、分发。

PS:"android.display"线程、"InputDispatcher"线程和"InputReader"线程均属于system_server进程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值