上一篇博客分析了InputReader中扫描码与键盘码的转化,今天我们再来分析下InputDispatcher

 

一、InputDispatcher的notifyKey函数

接上一篇我们我们分析到InputDispatcher的notifyKey函数:

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {    if (!validateKeyEvent(args->action)) {        return;    }    uint32_t policyFlags = args->policyFlags;    int32_t flags = args->flags;    int32_t metaState = args->metaState;    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {        policyFlags |= POLICY_FLAG_VIRTUAL;        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;    }    if (policyFlags & POLICY_FLAG_FUNCTION) {        metaState |= AMETA_FUNCTION_ON;    }    policyFlags |= POLICY_FLAG_TRUSTED;    int32_t keyCode = args->keyCode;    if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {        int32_t newKeyCode = AKEYCODE_UNKNOWN;        if (keyCode == AKEYCODE_DEL) {            newKeyCode = AKEYCODE_BACK;        } else if (keyCode == AKEYCODE_ENTER) {            newKeyCode = AKEYCODE_HOME;        }        if (newKeyCode != AKEYCODE_UNKNOWN) {            AutoMutex _l(mLock);            struct KeyReplacement replacement = {keyCode, args->deviceId};            mReplacedKeys.add(replacement, newKeyCode);            keyCode = newKeyCode;            metaState &= ~AMETA_META_ON;        }    } else if (args->action == AKEY_EVENT_ACTION_UP) {        // In order to maintain a consistent stream of up and down events, check to see if the key        // going up is one we've replaced in a down event and haven't yet replaced in an up event,        // even if the modifier was released between the down and the up events.        AutoMutex _l(mLock);        struct KeyReplacement replacement = {keyCode, args->deviceId};        ssize_t index = mReplacedKeys.indexOfKey(replacement);        if (index >= 0) {            keyCode = mReplacedKeys.valueAt(index);            mReplacedKeys.removeItemsAt(index);            metaState &= ~AMETA_META_ON;        }    }    KeyEvent event;    event.initialize(args->deviceId, args->source, args->action,            flags, keyCode, args->scanCode, metaState, 0,            args->downTime, args->eventTime);    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);//这个函数是调用了java的PhoneWindowManager    bool needWake;    { // acquire lock        mLock.lock();        if (shouldSendKeyToInputFilterLocked(args)) {            mLock.unlock();            policyFlags |= POLICY_FLAG_FILTERED;            if (!mPolicy->filterInputEvent(&event, policyFlags)) {                return; // event was consumed by the filter            }            mLock.lock();        }        int32_t repeatCount = 0;        KeyEntry* newEntry = new KeyEntry(args->eventTime,                args->deviceId, args->source, policyFlags,                args->action, flags, keyCode, args->scanCode,                metaState, repeatCount, args->downTime);        needWake = enqueueInboundEventLocked(newEntry);//将KeyEntry放入到队列中        mLock.unlock();    } // release lock    if (needWake) {        mLooper->wake();//唤醒进程    }}

我们先来看看mPolicy是构造函数中传进来的,那么我们就要去看InputManager中

InputDispatcher::InputDispatcher(const sp& policy) :    mPolicy(policy),

InputManager的构造函数,还是在InputManager中传入的,那么我们就要跟到NativeInputManager了。

 

InputManager::InputManager(        const sp& eventHub,        const sp& readerPolicy,        const sp& dispatcherPolicy) {    mDispatcher = new InputDispatcher(dispatcherPolicy);    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);

NativeInputManager是把自己传进来了,

 

 

NativeInputManager::NativeInputManager(jobject contextObj,        jobject serviceObj, const sp& 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;    }    mInteractive = true;    sp eventHub = new EventHub();    mInputManager = new InputManager(eventHub, this, this);

因此在InputDispatcher中调用interceptKeyBeforeQueueing,是调用了NativeInputManager的interceptKeyBeforeQueueing函数

void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,        uint32_t& policyFlags) {    // Policy:    // - Ignore untrusted events and pass them along.    // - Ask the window manager what to do with normal events and trusted injected events.    // - For normal events wake and brighten the screen if currently off or dim.    bool interactive = mInteractive.load();    if (interactive) {        policyFlags |= POLICY_FLAG_INTERACTIVE;    }    if ((policyFlags & POLICY_FLAG_TRUSTED)) {        nsecs_t when = keyEvent->getEventTime();        JNIEnv* env = jniEnv();        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);        jint wmActions;        if (keyEventObj) {            wmActions = env->CallIntMethod(mServiceObj,//反调用PhoneWindowManager                    gServiceClassInfo.interceptKeyBeforeQueueing,                    keyEventObj, policyFlags);            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {                wmActions = 0;            }            android_view_KeyEvent_recycle(env, keyEventObj);            env->DeleteLocalRef(keyEventObj);        } else {            ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");            wmActions = 0;        }        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);    } else {        if (interactive) {            policyFlags |= POLICY_FLAG_PASS_TO_USER;        }    }}

在这个函数中会反调到PhoneWindowManager中的interceptKeyBeforeQueueing函数,在上层的result返回result &= ~ACTION_PASS_TO_USER就不会发送到应用进程了。

返回结果保存在wmActions中,然后调用了handleInterceptActions函数:

 

void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,        uint32_t& policyFlags) {    if (wmActions & WM_ACTION_PASS_TO_USER) {        policyFlags |= POLICY_FLAG_PASS_TO_USER;    } else {    }}

如果PhoneWindowManager返回的是result &= ~ACTION_PASS_TO_USER,policyFlags |= POLICY_FLAG_PASS_TO_USER就没有了。

继续分析InputDispatcher::notifyKey函数,调用完interceptKeyBeforeQueueing,然后 新建了一个KeyEntry对象后,调用enqueueInboundEventLocked函数。

 

 

 

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {    bool needWake = mInboundQueue.isEmpty();    mInboundQueue.enqueueAtTail(entry);//放入队列尾    traceInboundQueueLengthLocked();    switch (entry->type) {    case EventEntry::TYPE_KEY: {//各个不同类型        // Optimize app switch latency.        // If the application takes too long to catch up then we drop all events preceding        // the app switch key.        KeyEntry* keyEntry = static_cast(entry);        if (isAppSwitchKeyEventLocked(keyEntry)) {            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {                mAppSwitchSawKeyDown = true;            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {                if (mAppSwitchSawKeyDown) {#if DEBUG_APP_SWITCH                    ALOGD("App switch is pending!");#endif                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;                    mAppSwitchSawKeyDown = false;                    needWake = true;                }            }        }        break;    }

继续分析InputDispatcher::notifyKey函数,最后会调用mLooper的wake函数唤醒线程,这个我们就不详细分析了。之前分析过。

 

 

 

二、InputDispatcher分发

notifyKey我们分析完了,接下来我们分析之前的InputDispatcherThread,线程不断的循环调用了InputDispatcher的dispatchOnce函数,下面我们来看下:

 

void InputDispatcher::dispatchOnce() {    nsecs_t nextWakeupTime = LONG_LONG_MAX;    { // acquire lock        AutoMutex _l(mLock);        mDispatcherIsAliveCondition.broadcast();        // Run a dispatch loop if there are no pending commands.        // The dispatch loop might enqueue commands to run afterwards.        if (!haveCommandsLocked()) {            dispatchOnceInnerLocked(&nextWakeupTime);//分发消息        }        // Run all pending commands if there are any.        // If any commands were run then force the next poll to wake up immediately.        if (runCommandsLockedInterruptible()) {            nextWakeupTime = LONG_LONG_MIN;        }    } // release lock    // Wait for callback or timeout or wake.  (make sure we round up, not down)    nsecs_t currentTime = now();    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);    mLooper->pollOnce(timeoutMillis);//进入epoll}

 

 

继续分析dispatchOnceInnerLocked函数

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {    ........    switch (mPendingEvent->type) {//根据类型不同    case EventEntry::TYPE_CONFIGURATION_CHANGED: {        ConfigurationChangedEntry* typedEntry =                static_cast(mPendingEvent);        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped        break;    }    case EventEntry::TYPE_DEVICE_RESET: {        DeviceResetEntry* typedEntry =                static_cast(mPendingEvent);        done = dispatchDeviceResetLocked(currentTime, typedEntry);        dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped        break;    }    case EventEntry::TYPE_KEY: {        KeyEntry* typedEntry = static_cast(mPendingEvent);        if (isAppSwitchDue) {            if (isAppSwitchKeyEventLocked(typedEntry)) {                resetPendingAppSwitchLocked(true);                isAppSwitchDue = false;            } else if (dropReason == DROP_REASON_NOT_DROPPED) {                dropReason = DROP_REASON_APP_SWITCH;            }        }        if (dropReason == DROP_REASON_NOT_DROPPED                && isStaleEventLocked(currentTime, typedEntry)) {            dropReason = DROP_REASON_STALE;        }        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {            dropReason = DROP_REASON_BLOCKED;        }        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);        break;    }    case EventEntry::TYPE_MOTION: {        MotionEntry* typedEntry = static_cast(mPendingEvent);        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {            dropReason = DROP_REASON_APP_SWITCH;        }        if (dropReason == DROP_REASON_NOT_DROPPED                && isStaleEventLocked(currentTime, typedEntry)) {            dropReason = DROP_REASON_STALE;        }        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {            dropReason = DROP_REASON_BLOCKED;        }        done = dispatchMotionLocked(currentTime, typedEntry,                &dropReason, nextWakeupTime);        break;    }    default:        ALOG_ASSERT(false);        break;    }    if (done) {        if (dropReason != DROP_REASON_NOT_DROPPED) {            dropInboundEventLocked(mPendingEvent, dropReason);        }        mLastDropReason = dropReason;        releasePendingEventLocked();        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately    }}

这个函数中,最后会根据类型不同调用不同的方法,我们是TYPE_KEY,调用了dispatchKeyLocked方法,一路跟下去有很多函数,我们就直接到最后的函数startDispatchCycleLocked函数:

 

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,        const sp& connection) {    while (connection->status == Connection::STATUS_NORMAL            && !connection->outboundQueue.isEmpty()) {        DispatchEntry* dispatchEntry = connection->outboundQueue.head;        dispatchEntry->deliveryTime = currentTime;        // Publish the event.        status_t status;        EventEntry* eventEntry = dispatchEntry->eventEntry;        switch (eventEntry->type) {        case EventEntry::TYPE_KEY: {            KeyEntry* keyEntry = static_cast(eventEntry);            // Publish the key event.            status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,                    keyEntry->deviceId, keyEntry->source,                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,                    keyEntry->keyCode, keyEntry->scanCode,                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,                    keyEntry->eventTime);            break;        }

这个函数会根据Event类型来分别处理,最后调用了connection对象的inputPublisher的publishKeyEvent函数。
 

 

 

下篇博客我们来继续分析下connection这个对象从何而来?

 

 



更多相关文章

  1. Android(安卓)H5 js webView初体验
  2. 简单的JNI调用
  3. Android中notifyDataSetInvalidated()和notifyDataSetChanged()
  4. 分析Cocos2d Android(安卓)项目的生成和运行
  5. [置顶] android学习系列-短信发送器与电话拨号器调用(3)
  6. android SystemUI 流程分析
  7. Dialog详解
  8. Android(安卓)AsyncTask两种线程池分析和总结
  9. Android四大组件安全问题

随机推荐

  1. Android开发者网址导航
  2. Android事件处理
  3. Android之——自动挂断电话的实现
  4. android animation动画
  5. Android编译系统分析大全
  6. Android(安卓)TextView属性详解
  7. Android中以JAR形式封装控件 或者类库
  8. 2019最新Android常用开源库总结(附带githu
  9. android 是通过 ksoap 连接 java xfire w
  10. 我所理解的Android模块化(二)——模块通信