android4.3 按鍵訊息處理分析

來源:互聯網
上載者:User

標籤:android4.3   按鍵訊息處理   

Android4.3按鍵訊息處理與之前的版本有稍微的區別,基本原理還是一樣的,這裡主要從兩個階段來分析:

1.前期的準備工作,即開機時啟動相應的的線程,靜候按鍵事件的來臨

2.當有按鍵訊息時,進行訊息的分發等處理

先看一張類圖:


從類圖中看出,主要涉及到的類有PhoneWindowManager、WindowManagerService、inputManagerService、 InputManager

先看第一個問題,前期的準備工作:

1.開機時先啟動inputManagerService,由ServerThread負責啟動;

  inputManager = new InputManagerService(context, wmHandler);            Slog.i(TAG, "Window Manager");            wm = WindowManagerService.main(context, power, display, inputManager,                    uiHandler, wmHandler,                    factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,                    !firstBoot, onlyCore);            ServiceManager.addService(Context.WINDOW_SERVICE, wm);            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);            ActivityManagerService.self().setWindowManager(wm);            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());            inputManager.start();

看inputManagerService的建構函式:

 

 public InputManagerService(Context context, Handler handler) {        this.mContext = context;        this.mHandler = new InputManagerHandler(handler.getLooper());        mUseDevInputEventForAudioJack =                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="                + mUseDevInputEventForAudioJack);        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());    }
先new一個InputManagerHandler,然後調用一個native方法,把service和handler的訊息佇列作為參數傳入,

nativeInit對應是com_android_server_input_InputManagerService.cpp中的nativeInit,,這個通過JNI的機制進行關聯。

這裡不多說,看nativeInit:

static jint 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<jint>(im);}
這裡主要是建立一個NativeInputManager對象,看起建構函式:

NativeInputManager::NativeInputManager(jobject contextObj,        jobject serviceObj, const sp<Looper>& looper) :        mLooper(looper) {    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;    }    sp<EventHub> eventHub = new EventHub();    mInputManager = new InputManager(eventHub, this, this);}
這裡主要是建立一個InputManager,看起建構函式:

InputManager::InputManager(        const sp<EventHubInterface>& eventHub,        const sp<InputReaderPolicyInterface>& readerPolicy,        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {    mDispatcher = new InputDispatcher(dispatcherPolicy);    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);    initialize();}void InputManager::initialize() {    mReaderThread = new InputReaderThread(mReader);    mDispatcherThread = new InputDispatcherThread(mDispatcher);}

這裡看到了建立對象InputDispatcher 、InputReader以及兩個時刻在跑的線程對象:mReaderThread、mDispatcherThread

至此初始化的第一步是完成了,但建立的線程還沒start,還開始正真的幹活,看開啟過程


至此前期的準備工作都做完,兩線程開始幹活,靜候按鍵事件來臨

2.當有按鍵事件時兩個線程處理流程見:


兩條主線:

a.  InputReader從EventHub中擷取到按鍵事件,並通知InputDispatcher;InputDispatcher接到通知後調用

     interceptKeyBeforeQueueing方法進行相關的操作,並把按鍵事件加入到隊列中,等待後面處理。

    排入佇列源碼:

    

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {    bool needWake = mInboundQueue.isEmpty();    mInboundQueue.enqueueAtTail(entry);    traceInboundQueueLengthLocked();

b.  InputDispatcher從訊息佇列中擷取按鍵訊息,調用interceptKeyBeforeDispatching方法判斷是否對此訊息進行攔截,

   根據其結果進行判斷:

  

    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,            &event, entry->policyFlags);    mLock.lock();    if (delay < 0) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;    } else if (!delay) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;    } else {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;        entry->interceptKeyWakeupTime = now() + delay;    }


其中在InputDispatcher中調用的interceptKeyBeforeQueueing和interceptKeyBeforeDispatching方法都是對應著

PhoneWindowManager中的同名方法。

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.