上层的对按键事件的侦听和纷发处理是通过inputmanager及其组件inputreader,inputdispatch,eventhub构成的。

在system_server被创建的时候就会创建WMS,并调用inputmanager的start方法来启动read和dispatch线程。

 

1.      Inputmanager的创建

Systemserver的ServerThread的run函数中,会调用WMS的main方法来创建WMS

     

Slog.i(TAG, "WindowManager");
            wm = WindowManagerService.main(context,power,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
           ServiceManager.addService(Context.WINDOW_SERVICE, wm);

再来看windowmanagerservice的main方法:

public static WindowManagerServicemain(Context context,
            PowerManagerService pm, booleanhaveInputMethods) {
        WMThread thr = new WMThread(context, pm, haveInputMethods);
        thr.start();
 
        synchronized (thr) {
            while (thr.mService == null) {
                try {
                    thr.wait();
                } catch (InterruptedExceptione) {
                }
            }
        }
 
        return thr.mService;

}此方法很简单,就是创建了WMThread,然后调用了他的start方法。

继续看WMThread:它的构造函数很简单,就是给几个变量赋值,重点看看它的run函数:

public void run() {
            Looper.prepare();
            WindowManagerService s = new WindowManagerService(mContext, mPM,
                    mHaveInputMethods);
            android.os.Process.setThreadPriority(
                   android.os.Process.THREAD_PRIORITY_DISPLAY);
           android.os.Process.setCanSelfBackground(false);
 
            synchronized (this) {
                mService = s;
                notifyAll();
            }
 
            Looper.loop();
        }

此方法创建了WMS的实例,继续跟进:

private WindowManagerService(Contextcontext, PowerManagerService pm,
            boolean haveInputMethods) {
//……..省略无关代码
        mInputManager = newInputManager(context, this);
//……
}

看看inputmanager的构造函数:inputmanager.java中

public InputManager(Context context,WindowManagerService windowManagerService) {
        this.mContext = context;
        this.mWindowManagerService =windowManagerService;
        
        this.mCallbacks = new Callbacks();
        
        init();
   }

就是给几个变量赋值,调用了init :

private void init() {
        Slog.i(TAG, "Initializing inputmanager");
        nativeInit(mCallbacks);
   }

调用nativeInit ,此方法对应了com_android_server_inputmanager.java中的

android_server_InputManager_nativeInit(sourceinsight搜一下即可,就是inputmanger对应的JNI的部分。)
staticvoid android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
        jobject callbacks) {
    if (gNativeInputManager == NULL) {
       gNativeInputManager = new NativeInputManager(callbacks);
    } else {
        LOGE("Input manager alreadyinitialized.");
        jniThrowRuntimeException(env,"Input manager already initialized.");
    }

}此方法也是直接调用了NativeInputManager的构造函数:

NativeInputManager::NativeInputManager(jobjectcallbacksObj) :
    mFilterTouchEvents(-1),mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
    mMaxEventsPerSecond(-1),
    mDisplayWidth(-1), mDisplayHeight(-1),mDisplayOrientation(ROTATION_0) {
    JNIEnv* env = jniEnv();
 
    mCallbacksObj =env->NewGlobalRef(callbacksObj);
 
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub,this, this);

}此方法中做了两件很重要的事情,创建了EventHub并将其作为入参传入了InputManager,此处的inputmanager是native的,即是inputmanager.cpp中的。

Inputmanager.cpp   
InputManager::InputManager(
        const sp<EventHubInterface>&eventHub,
        const sp<InputReaderPolicyInterface>&readerPolicy,
        constsp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();

}创建了inputdispatcher和inputreader,并调用了initialize函数创建了InputReaderThread和InputDispatcherThread。

到这里,相关的组件就创建完毕了,那么这些进程是怎么跑取来的呢?

2.      关键线程的启动:

我们还是回到WMS的构造函数中:

private WindowManagerService(Contextcontext, PowerManagerService pm,
            boolean haveInputMethods) {
         //。。。。。。省略
        mInputManager = new InputManager(context, this);
       PolicyThread thr = newPolicyThread(mPolicy, this, context, pm);
        thr.start();
 
        synchronized (thr) {
            while (!thr.mRunning) {
                try {
                    thr.wait();
                } catch (InterruptedExceptione) {
                }
            }
        }
 
        mInputManager.start();
}

创建完毕后,就会调用inputmanager的start函数,过程和creat相当的类似,都是用过JNI的调用到native的线程启动,下面依然一级一级的跟,首先是inputmanager的start:

public void start() {
        Slog.i(TAG, "Starting inputmanager");
        nativeStart();
   }

直接调用了nativeStart,对应的是com_android_server_inputmanager.java中的

android_server_InputManager_nativeStart
staticvoid android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
    if (checkInputManagerUnitialized(env)) {
        return;
    }
 
    status_tresult = gNativeInputManager->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env,"Input manager could not be started.");
    }
}

gNativeInputManager即是上面在创建的时候,通过NativeInputManager的构造函数获取的,而getInputManager的声明为:

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

 

直接返回mInputManager,而mInputManager也是在NativeInputManager的构造函数调用的。所以,实际调用的应该是native的inputmanager的start函数:

Inputmanager.cpp 
status_tInputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher",PRIORITY_URGENT_DISPLAY);
    if (result) {
        LOGE("Could not startInputDispatcher thread due to error %d.", result);
        return result;
    }
 
    result = mReaderThread->run("InputReader",PRIORITY_URGENT_DISPLAY);
    if (result) {
        LOGE("Could not start InputReaderthread due to error %d.", result);
 
        mDispatcherThread->requestExit();
        return result;
    }
 
    return OK;
}

到这里,这两个线程就跑起来了,mDispatcherThread负责按键事件的纷发。mReaderThread负责按键事件的获取,接下来用power键的处理作为一个例子,来过下按键事件的简单流程。

3.      按键捕获:

mReaderThread->run后会走到他的threadLoop函数:
boolInputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

调用了inputreader的looponce函数:

voidInputReader::loopOnce() {
   RawEvent rawEvent;
    mEventHub->getEvent(& rawEvent);
 
#ifDEBUG_RAW_EVENTS
    LOGD("Input event: device=0x%xtype=0x%x scancode=%d keycode=%d value=%d",
            rawEvent.deviceId, rawEvent.type,rawEvent.scanCode, rawEvent.keyCode,
            rawEvent.value);
#endif
 
    process(& rawEvent);
}

首先是从eventhub中获取事件,再将其传入process中,eventhub的工作机理还没搞清楚,将在下一篇中分析。

根据返回的rawevent中的类型,会做不同的处理:

voidInputReader::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EventHubInterface::DEVICE_ADDED:
        addDevice(rawEvent->deviceId);
        break;
 
    case EventHubInterface::DEVICE_REMOVED:
        removeDevice(rawEvent->deviceId);
        break;
 
    caseEventHubInterface::FINISHED_DEVICE_SCAN:
       handleConfigurationChanged(rawEvent->when);
        break;
 
    default:
        consumeEvent(rawEvent);
        break;
    }
}

如果是power键,会走到consumeEvent


voidInputReader::consumeEvent(const RawEvent* rawEvent) {
    int32_t deviceId = rawEvent->deviceId;
 
    { // acquire device registry reader lock
        RWLock::AutoRLock_rl(mDeviceRegistryLock);
 
        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
        if (deviceIndex < 0) {
            LOGW("Discarding event forunknown deviceId %d.", deviceId);
            return;
        }
 
        InputDevice* device =mDevices.valueAt(deviceIndex);
        if (device->isIgnored()) {
            //LOGD("Discarding event forignored deviceId %d.", deviceId);
            return;
        }
 
        device->process(rawEvent);
    } // release device registry reader lock

}通过刚刚传入的diviceid找到对应的deviceindex,而这些device的创建和销毁正是上步中的ADD/REMOVEdevice 。

最后调用device的process

voidInputDevice::process(const RawEvent* rawEvent) {
    size_t numMappers = mMappers.size();
    for (size_t i = 0; i < numMappers; i++){
        InputMapper* mapper = mMappers[i];
        mapper->process(rawEvent);
    }

}调用在creatdevice时添加的mapper的process,我们这里是power键,所以应该是KeyboardInputMapper(详见creatdevice函数)

voidKeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EV_KEY: {
        int32_t scanCode =rawEvent->scanCode;
        if (isKeyboardOrGamepadKey(scanCode)) {
            processKey(rawEvent->when,rawEvent->value != 0, rawEvent->keyCode, scanCode,
                    rawEvent->flags);
        }
        break;
    }
    }
}

通过判断scan code,确认是否为键盘或者游戏手柄,如果是则走到processkey:

voidKeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
       int32_t scanCode, uint32_t policyFlags) {
   int32_t newMetaState;
   nsecs_t downTime;
   bool metaStateChanged = false;
 
{ // ……省略此处对按键的处理
 
    getDispatcher()->notifyKey(when,getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN :AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM,keyCode, scanCode, newMetaState, downTime);
}

此处就会通知dispatch,有按键上报。

voidInputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
        uint32_t policyFlags, int32_t action,int32_t flags,
        int32_t keyCode, int32_t scanCode,int32_t metaState, nsecs_t downTime) {
      //,,,,,….
 
    mPolicy->interceptKeyBeforeQueueing(eventTime,deviceId, action, /*byref*/ flags,
            keyCode, scanCode, /*byref*/policyFlags);
}

此处的mPolicy就是创建inputdispatch的时候传入的,可以看出,这个mPolicy就是NativeInputManager的this。(NativeInputManager::NativeInputManager创建native的inputmanager的时候传入)

所以,此处的interceptKeyBeforeQueueing实际是NativeInputManager的interceptKeyBeforeQueueing:

而在此函数中会调用WMS的interceptKeyBeforeQueueing,询问其是否会对此按键做特殊处理,实际是在phonewindowmanager中处理的,接下来的流程已经在上一篇中讲过,不再赘述,下一篇中打算将eventhub的流程,尤其是按键扫描的对应搞清楚。