android4.0 Power、home、menu等按鍵處理分析

一、Power、Home、Menu、back以及Vol+、Vol-的處理

我們知道,在WindowManagerService創建的時候會聲明一個InputManager的實例,這個InputManager又會通過NativeInit實現將mCallbacks、looper等添加到C++中實現創建InputDispatcher和InputReader。然後將這兩個實例各加入到InputDispatcherThread和InputReaderThread之中,實現讀取輸入事件並且進行派發。

1、InputManager.java:

構造函數中有如下實現:

this.mCallbacks = new Callbacks();

這個很關鍵,它就是在C++層實現回調的方法。然後通過NativeInit添加到C++中去瞭。

private final class Callbacks {

        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean

isScreenOn) {

            return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(

                    event, policyFlags, isScreenOn);

        }

        public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {

           return mWindowManagerService.mInputMonitor.

interceptMotionBeforeQueueingWhenScreenOff(policyFlags);

        }

……

}

這些都是通過WindowManagerService調用mPolicy的實現具體功能的函數

2、com_android_server_InputManager.cpp

在android_server_InputManager_nativeInit函數中又有如下操作:

gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);

這裡又將InputManager.java中實現的callbacks放到瞭NativeInputManager中的mCallbacksObj瞭。

同時構建InputManager:mInputManager = new InputManager(eventHub, this, this);

3、InputManager.cpp

在構造函數中有:

    mDispatcher = new InputDispatcher(dispatcherPolicy);

    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);

再由

class NativeInputManager : public virtual RefBase,

    public virtual InputReaderPolicyInterface,

    public virtual InputDispatcherPolicyInterface,

    public virtual PointerControllerPolicyInterface {

}我們可以知道,InputManager的構造函數的第二個參數實際上就是InputDispatcherPolicyInterface的實現,也就是com_android_server_InputManager的實例。

由InputDispatcher的聲明我們知道,這裡policy自然就是com_android_server_InputManager瞭

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :

mPolicy(policy),

    mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),

    mNextUnblockedEvent(NULL),

    mDispatchEnabled(true), mDispatchFrozen(false), mInputFilterEnabled(false),

    mCurrentInputTargetsValid(false),

    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE)

在InputReader讀取事件之後會喚醒InputDiapatcher函數,之後就開始調用InputDispatcher::notifyKey。詳細分析參見:

http://blog.csdn.net/luoshengyang/article/details/6882903

4、InputDispatcher.cpp

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {

……

//這裡的mPolicy是InputManager

mPolicy->interceptKeyBeforeQueueing(&event, policyFlags);

……

}

5、回到com_android_server_InputManager:

void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,

        uint32_t& policyFlags) {

if ((policyFlags & POLICY_FLAG_TRUSTED)) {

if (keyEventObj) {

//這裡,我們清晰地看到,mCallbacksObj是InputManager.java中的Callbacks瞭

//也就是調用它的interceptKeyBeforeQueueing瞭

            wmActions = env->CallIntMethod(mCallbacksObj,

                    gCallbacksClassInfo.interceptKeyBeforeQueueing,

                    keyEventObj, policyFlags, isScreenOn);

            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {

                wmActions = 0;

            }

            android_view_KeyEvent_recycle(env, keyEventObj);

            env->DeleteLocalRef(keyEventObj);

        }

}

}

我們回到步驟1的Callbacks定義:

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean

isScreenOn) {

            return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(

                    event, policyFlags, isScreenOn);

}

InputMonitor.java

    public int interceptKeyBeforeQueueing(

            KeyEvent event, int policyFlags, boolean isScreenOn) {

        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);

    }

這裡mService是WindowManagerService,mPolicy 則是如下定義(WindowManagerService中)

final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();

PolicyManager.java

public static WindowManagerPolicy makeNewWindowManager() {

//sPolicy就是Policy的實例化

        return sPolicy.makeNewWindowManager();

}

Policy.java

    public WindowManagerPolicy makeNewWindowManager() {

        return new PhoneWindowManager();

}

至此,正式調用PhoneWindowManager的實例。

因此處理hardkey的相關代碼是在PhoneWindowManager中瞭

作者:kakaBack

發佈留言