Chinaunix首页 | 论坛 | 博客
  • 博客访问: 377900
  • 博文数量: 160
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 250
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-18 01:16
文章分类

全部博文(160)

文章存档

2016年(4)

2015年(13)

2014年(29)

2013年(114)

我的朋友

分类: Android平台

2014-01-17 10:49:39

上层的对按键事件的侦听和纷发处理是通过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 = new EventHub();

    mInputManager = new InputManager(eventHub,this, this);

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

Inputmanager.cpp  

InputManager::InputManager(

        const sp&eventHub,

        const sp&readerPolicy,

        constsp& 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 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的流程,尤其是按键扫描的对应搞清楚

阅读(2011) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~