当前位置: 代码迷 >> 综合 >> AndroidR Input子系统(2)Input子系统的启动
  详细解决方案

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

热度:5   发布时间:2024-03-06 00:51:02.0

分析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层MessageQueuesp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);if (messageQueue == nullptr) {
    jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}//创建NativeInputManagerNativeInputManager* 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;//创建InputManagermInputManager = 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) {
    //创建自己的LoopermLooper = 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 lockAutoMutex _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);//创建inotifymINotifyFd = 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为mINotifyFdeventItem.data.fd = mINotifyFd;//将mINotifyFd添加到epollint 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;//将读管道添加到epollresult = 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,并传入InputClassifiermQueuedListener = new QueuedInputListener(listener);{
     // acquire lockAutoMutex _l(mLock);refreshConfigurationLocked(0);updateGlobalMetaStateLocked();} // release lock
}

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

//SystemService.javaprivate 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()函数。
  相关解决方案