Android事件输入系统简单介绍

InputDispatcher这个类,它是Android事件输入系统的重要组成部分,整个Android事件输入系统可以分为几个部分。其首当其冲的是InputReader,其主要作用是将输入事件从硬件节点中读取后转化为一个Event事件,并将该事件分发给InputDispatcher,InputDispatcher的职责就是接收来自InputReader的Event事件,并像其名字所述的一样,将事件 发送给合适的窗口,并监控ANR的发生;然后则是创建InputReader和InputDispatcher的父类 (InputManager),由其创建两者并提供Policy对事件进行预处理;最后则是涉及系统Service以及面向用户的几个相关模块,如ActivityManager、WindowManager和View等。

在Android4.4中,事件输入的Service部分在/frameworks/base/services/input下,而在Android5.0中该部分实现至/frameworks/native/services/inputflinger/下,虽然我们将整个事件输入系统分为如上4个部分,但是,在android中负责管理事件输入是InputManagerService,其也是系统级的Service之一。

Android8.0中InputManagerServce在 base/services/core/java/com/android/server/input

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
        ... ...
}



public final class SystemServer {
... ...
}

/**
 * Starts a miscellaneous grab bag of stuff that has yet to be refactored
 * and organized.
 */
#SystemServer 
private void startOtherServices() {
InputManagerService inputManager = null;
... ...

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

}

从上述源码中可以看到,在SystemServer的startOtherServices方法中,不但构造并且启动了InputManagerService,而且在启动InputManagerService之前将它自身注入到WindowManagerService中进行关联。InputManagerService的构造函数主要是对native层初始化,但是它的实现逻辑非常复杂。

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);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();

    mContextObj = env->NewGlobalRef(contextObj);
    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;
    }
    mInteractive = true;

    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}

//在NativeInputManager的逻辑中,首先会创建一个EventHub来监听所有事件的输入。

#InputManagerService 
public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {

}


#InputManagerService 
  public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

        String doubleTouchGestureEnablePath = context.getResources().getString(
                R.string.config_doubleTouchGestureEnableFile);
        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
            new File(doubleTouchGestureEnablePath);

        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }

#InputManagerService
private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);

这里主要是调用了nativeInit方法进行一些列的初始化操作,nativeInit 方法实现在native层,在其中构造了NativeInputManager对象。

之后就会相继初始化InputManager、InputDispatcher、InputReader、InputReaderThread和InputDispatcherThread。其中InputReaderThread 和

InputDispatcherThread是又InputManager管理的重要线程,其作用和具体的逻辑均与InputReader 和 InputDispatcher 相关。这一系列的初始化操作完毕后,InputManagerService就会在SystemServer里调用其start方法开始运作,其中最为主要的是,使上面提到的两个线程InputReaderThread 和 InputDispatcherThread 运作。InputReaderThread 启动后会进入死循环,每次循环都会调用loopOnce函数,第一次循环时会扫描/dev/input/设备节点目录,并通过ioctl函数获取设备信息以及判断其类型,当设备发生改变后则会通NativeInputManager 的回调函数通知处于java层的InputManagerService做出相应的处理。如上所述,InputReaderThread只负责从设备端读取事件信息,每一个事件信息在InputReaderThread里最终都会被封装为一个NotifyArgs对象,通过NotifyArgs中的Notify方法调用到InputDispatcher相应的Notify接口,并由InputDispatcher来完成事件的分派。

 

 

 

扫描二维码关注公众号,回复: 8699663 查看本文章

参考《Android源码设计模式》

发布了161 篇原创文章 · 获赞 154 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zhangying1994/article/details/86979224