AndroidR Input子系统(2)Input子系统的启动

语言: CN / TW / HK

分析Input子系统的启动主要是看InputManagerService的启动,InputManagerService是java层的一个系统服务,继承IInputManager.Stub,作为binder服务端,在SystemServer中启动:

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
   
   
            ......
            t.traceBegin("StartInputManagerService");
            inputManager = new InputManagerService(context);
            t.traceEnd();
            ......
     }

InputManagerService

public InputManagerService(Context context) {
   
   
        this.mContext = context;
        //创建handler,运行在"android.display"线程
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        ......
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

        
    }

InputManagerService构造函数中创建了一个InputManagerHandler,使用的是"android.display"线程的looper对象,运行在"android.display"线程。

nativeInit

// com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
   
   
    //java层MessageQueue的mPtr指向native层MessageQueue,这里
    //就是将mPtr强转为native层MessageQueue
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
   
   
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    //创建NativeInputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

nativeInit实际上就做了一件事,拿到java层InputManagerService传递下来的"android.display"线程的Looper对应的MessageQueue获取native层MessageQueue,之后通过此native层MessageQueue的Looper创建NativeInputManager

NativeInputManager

// com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
   
   
    JNIEnv* env = jniEnv();
    //java层的InputManagerService对象
    mServiceObj = env->NewGlobalRef(serviceObj);

    {
   
   
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
        mLocked.pointerCapture = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;
    //创建InputManager
    mInputManager = new InputManager(this, this);
    //将mInputManager添加到ServiceManager,可以通过getService获取
    defaultServiceManager()->addService(String16("inputflinger"),
            mInputManager, false);
}

NativeInputManager构造函数也很简单,就是创建了InputManager,并添加到ServiceManager,InputManager是binder服务端,它的构造函数中接收两个对象:InputReaderPolicyInterfaceInputDispatcherPolicyInterface

public:
    InputManager(
            const sp<InputReaderPolicyInterface>& readerPolicy,
            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);

NativeInputManager是这两个对象的子类,所以传递的是this

class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface {
   
   

InputManager

InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
   
   
    //(1)
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    //(2)
    mClassifier = new InputClassifier(mDispatcher);
    //(3)
    mReader = createInputReader(readerPolicy, mClassifier);
}

InputManager构造函数中创建了这三个对象:

private:
    sp<InputDispatcherInterface> mDispatcher;
    
    sp<InputClassifierInterface> mClassifier;
    
    sp<InputReaderInterface> mReader; 
};

现在来分别看看这三个对象的初始化过程,首先看(1):mDispatcher = createInputDispatcher(dispatcherPolicy)

createInputDispatcher

//InputDispatcherFactory.cpp
sp<InputDispatcherInterface> createInputDispatcher(
        const sp<InputDispatcherPolicyInterface>& policy) {
   
   
    return new android::inputdispatcher::InputDispatcher(policy);
}

这里简单粗暴的直接new了一个InputDispatcherInputDispatcherInputDispatcherInterface的子类,InputDispatcher是一个非常重要的对象,它是Input事件发送到对应窗口的分发者

// --- InputDispatcher ---

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
      : mPolicy(policy),
        mPendingEvent(nullptr),
        mLastDropReason(DropReason::NOT_DROPPED),
        mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
        mAppSwitchSawKeyDown(false),
        mAppSwitchDueTime(LONG_LONG_MAX),
        mNextUnblockedEvent(nullptr),
        mDispatchEnabled(false),
        mDispatchFrozen(false),
        mInputFilterEnabled(false),
        // mInTouchMode will be initialized by the WindowManager to the default device config.
        // To avoid leaking stack in case that call never comes, and for tests,
        // initialize it here anyways.
        mInTouchMode(true),
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
   
   
    //创建自己的Looper
    mLooper = new Looper(false);
    mReporter = createInputReporter();

    mKeyRepeatState.lastKeyEntry = nullptr;
    //获取java层的一些配置参数,写到mConfig中,主要就是如下两个值: 
    //public static final int DEFAULT_LONG_PRESS_TIMEOUT = 400;
    //private static final int KEY_REPEAT_DELAY = 50;
    policy->getDispatcherConfiguration(&mConfig);
}

接着再看第二个对象:(2)
mClassifier = new InputClassifier(mDispatcher);

// --- InputClassifier ---
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
      : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {
   
   }

它的构造函数非常简单,将前面创建的InputDispatcher保存在了mListener中,并创建了一个监听HAL的死亡回调对象,InputClassifierM是一个空壳子,它提供的如下函数内部实现都是调用到了InputDispatcher中去:

class InputClassifier : public InputClassifierInterface {
   
   
public:
    explicit InputClassifier(const sp<InputListenerInterface>& listener);

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

再看第三个对象(3)
mReader = createInputReader(readerPolicy, mClassifier);

sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
   
   
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

同样是直接new的一个InputReader,它接收了一个EventHub对象,这个对象非常重要,它是读取驱动原始Input事件的主要类,InputReader构造函数比较简单,代码不多,所以我们先来分析EventHub的初始化。

// --- InputReader ---

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

    {
   
    // acquire lock
        AutoMutex _l(mLock);

        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

EventHub继承EventHubInterface,这是它的构造函数:


EventHub::EventHub(void)
      : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
        mNextDeviceId(1),
        mControllerNumbers(),
        mOpeningDevices(nullptr),
        mClosingDevices(nullptr),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false),
        mNeedToScanDevices(true),
        mPendingEventCount(0),
        mPendingEventIndex(0),
        mPendingINotify(false) {
   
   
    ensureProcessCanBlockSuspend();
    //创建epoll,对EPOLL_CLOEXEC个fd进行监听
    mEpollFd = epoll_create1(EPOLL_CLOEXEC);

    //创建inotify
    mINotifyFd = inotify_init();
    //对"/dev/input"目录下的文件进行监听,监听事件是文件的创建与删除
    mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    
    if (isV4lScanningEnabled()) {
   
   
        //对"/dev"目录进行监听
        mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
        
    } else {
   
   
        mVideoWd = -1;
        
    }
    //创建epoll事件结构体
    struct epoll_event eventItem = {
   
   };
    //监听事件:
    //EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
    //EPOLLWAKEUP:系统会在事件排队时就保持唤醒,从epoll_wait调用开始,持续要下一次epoll_wait调用

    eventItem.events = EPOLLIN | EPOLLWAKEUP;
    //epoll监听的fd为mINotifyFd
    eventItem.data.fd = mINotifyFd;
    //将mINotifyFd添加到epoll
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    
    int wakeFds[2];
    //创建管道
    result = pipe(wakeFds);
   
    //读管道
    mWakeReadPipeFd = wakeFds[0];
    //写管道
    mWakeWritePipeFd = wakeFds[1];
    //将读写管道都设置为非阻塞
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
   

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

如果有看过我前一篇文章AndroidR Input子系统(1)INotify与Epoll机制就会对上面这段代码非常熟悉了,简单总结下INotify与Epoll:
INotify的用法分为三步:

  1. 使用inotify_init创建一个inotify对象
  2. 使用inotify_add_watch对文件路径进行监听
  3. 使用read读取监听到的事件

Epoll的使用步骤也很简单:

  1. 通过epoll_create创建epoll对象
  2. 为需要监听的fd构建一个epoll_event结构体,并注册到epoll_ctl进行监听
  3. 调用epoll_wait进入监听状态,传入一个epoll_event结构体数组,用于收集监听到的事件
  4. 遍历第三步的epoll_event结构体数组,依次取出事件处理

EventHub构造函数中结合INotify与Epoll对"/dev/input"目录进行监听,以及创建了一对管道,将读端mWakeReadPipeFd添加到Epoll进行监听,之后只需要调用epoll_wait等待事件发生就行了,至于在哪里调的epoll_wait,我们后面再看。

EventHub创建完之后再回来看InputReader,它的构造函数就比较简单了。

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
      : mContext(this),
        mEventHub(eventHub),
        mPolicy(policy),
        mGlobalMetaState(0),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
   
   
        //创建QueuedInputListener,并传入InputClassifier
    mQueuedListener = new QueuedInputListener(listener);

    {
   
    // acquire lock
        AutoMutex _l(mLock);

        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

到此InputManager的构造函数中创建的三个对象InputDispatcherInputClassifierInputReader就分析完了,即InputManagerService构造方法中调用的nativeInit函数就结束了,接着再回到SystemService中,InputManagerService创建完成之后,会调用它的start方法:

//SystemService.java
 private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
   
   
 		......
 		inputManager = new InputManagerService(context);		
 		......
 		inputManager.start();
 		.....
 }

InputManagerService.start

//InputManagerService.java
public void start() {
   
   
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);

        // 添加Watchdog的监听
        Watchdog.getInstance().addMonitor(this);
        
        //注册一系列Settings数据库值的监听
        .....
    }

这个方法中我们关注的是nativeStart这个方法,mPtr指向nativeInit中创建的NativeInputManager

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
   
   
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    status_t result = im->getInputManager()->start();
    if (result) {
   
   
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

NativeInputManagergetInputManager返回nativeStart创建的InputManager,调用其start函数:

status_t InputManager::start() {
   
   
    //(1)
    status_t result = mDispatcher->start();
    if (result) {
   
   
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }
    //(2)
    result = mReader->start();
    if (result) {
   
   
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcher->stop();
        return result;
    }

    return OK;
}

这个函数中非常重要的两步就是分别调用了InputDispatcherInputReaderstart函数,首先来看(1):

//InputDispatcher.cpp
status_t InputDispatcher::start() {
   
   
    if (mThread) {
   
   
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() {
   
    dispatchOnce(); }, [this]() {
   
    mLooper->wake(); });
    return OK;
}

mThread如果已经存在则返回,否则创建,mThread类型为InputThreadInputThread内部有一个ThreadInputThread的构造函数中接受三个参数:

class InputThread {
   
   
public:
    explicit InputThread(std::string name, std::function<void()> loop,
                         std::function<void()> wake = nullptr);

一个string,代表此线程名称,还有两个std::function,传递的则是两个Lambda表达式,这两个Lambda表达式中分别调用dispatchOnce()mLooper->wake()这两个函数,接着再看InputThread构造函数的具体实现:

//InputThread.cpp
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
      : mName(name), mThreadWake(wake) {
   
   
    mThread = new InputThreadImpl(loop);
    mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

InputThread构造函数中将接收的两个Lambda表达式一个传递给了InputThreadImpl,另一个保存在了自己mThreadWake中,
InputThreadImpl继承Thread,是一个线程,
接着调用run函数启动线程,线程启动之后就会调用自己的threadLoop函数:

class InputThreadImpl : public Thread {
   
   
public:
    explicit InputThreadImpl(std::function<void()> loop)
          : Thread(/* canCallJava */ true), mThreadLoop(loop) {
   
   }

    ~InputThreadImpl() {
   
   }

private:
    std::function<void()> mThreadLoop;

    bool threadLoop() override {
   
   
        mThreadLoop();
        return true;
    }
};

InputThreadImplthreadLoop函数很简单,调用了自己的mThreadLoop函数,mThreadLoop接收了一个Lambda表达式:([this]() { dispatchOnce(); }),即
InputThreadImpl
线程启动时就会调用InputDispatcherdispatchOnce函数,至于dispatchOnce的细节我们在后面再分析。

接着我们再来看看InputReaderstart函数:

status_t InputReader::start() {
   
   
    if (mThread) {
   
   
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() {
   
    loopOnce(); }, [this]() {
   
    mEventHub->wake(); });
    return OK;
}

InputReaderstart函数就和InputDispatcher有异曲同工之妙了,只不过线程的名字和两个Lambda表达式不一样,所以我们知道最终这个线程启动之后会调用InputReaderloopOnce()函数。

到此Input系统的启动篇就分析完了,我们大致总结一下:

  1. SystemServer创建InputManagerService这个系统服务。
  2. InputManagerService构造方法中创建"android.display"线程,调用nativeInit函数,将"android.display"线程的Looper对应的MessageQueue传递到native层。
  3. nativeInit函数中创建NativeInputManager对象,并将其指针返回到java层mPtr保存。
  4. NativeInputManager构造函数中创建InputManager对象,并将其注册到ServiceManager,其服务名称为:“inputflinger”,InputManager构造函数中创建三个重要对象:InputDispatcherInputClassifierInputReader,比较重要的是在构造InputReader是创建了EventHub对象。
  5. EventHub构造函数中通过inotify和epoll机制对目录"/dev/input"监听,主要监听此目录下文件的创建和删除,到此nativeInit函数完毕。
  6. SystemServer中会接着调用InputManagerServicestart方法,此方法中调用nativeStart作进一步初始化,nativeStart函数中调用InputManagerstart函数。
  7. InputManagerstart函数中分别调用了InputDispatcherInputReaderstart函数,即分别启动了其内部线程InputThreadImplInputDispatcher内部线程(名字:“InputDispatcher”)启动调用了自己的dispatchOnce()函数,InputReader内部线程(名字:“InputReader”)启动调用了自己的loopOnce()函数。
分享到: