Android6.0 按键流程 InputDispatcher分发输入消息(三)
来源:互联网 发布:scilab 矩阵 编辑:程序博客网 时间:2024/05/11 18:45
一、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<InputDispatcherPolicyInterface>& policy) :
- mPolicy(policy),
InputManager的构造函数,还是在InputManager中传入的,那么我们就要跟到NativeInputManager了。
- InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- NativeInputManager::NativeInputManager(jobject contextObj,
- jobject serviceObj, const sp<Looper>& 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> 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 {
- }
- }
继续分析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<KeyEntry*>(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我们分析完了,接下来我们分析之前的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<ConfigurationChangedEntry*>(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<DeviceResetEntry*>(mPendingEvent);
- done = dispatchDeviceResetLocked(currentTime, typedEntry);
- dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
- break;
- }
- case EventEntry::TYPE_KEY: {
- KeyEntry* typedEntry = static_cast<KeyEntry*>(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<MotionEntry*>(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>& 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<KeyEntry*>(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这个对象从何而来?
转载地址
http://blog.csdn.net/kc58236582/article/details/50611208
- Android6.0 按键流程(三)InputDispatcher分发输入消息
- Android6.0 按键流程 InputDispatcher分发输入消息(三)
- Android输入子系统之InputDispatcher分发键盘消息过程分析
- Android6.0 按键流程(六)应用进程处理按键消息
- Android6.0 按键流程(一)读取设备事件
- Android6.0 按键流程(四)registerInputChannel函数
- Android6.0 按键流程(一)读取设备事件
- Android6.0 按键流程 registerInputChannel函数(四)
- Android Input流程分析(四):InputDispatcher
- inputdispatcher按键的派发
- Android6.0 按键流程(二)KeyboardInputMapper扫描码转成键盘码
- Android6.0 按键流程(五)无线鼠标右键无效 -- hal层
- Android6.0 按键流程(七)无线鼠标右键无效 -- Framework层
- Android6.0 按键流程 读取设备事件(一)
- [RK3288][Android6.0] 系统按键驱动流程分析
- Android input处理机制(三)InputDispatcher
- 按键消息派发流程
- Android中按键消息分发机制 上
- Android电话拦截demo
- DNS IP地址分类 ISP缓存
- 软件测试流程(一)
- 驱动:中断以及实现防抖
- 关于file_get_contents("php://input")
- Android6.0 按键流程 InputDispatcher分发输入消息(三)
- 测试工具LoadRunner的安装与破解
- 用PHPExcel读取excel文件内容
- [BZOJ4289]PA2012 Tax 差分建图+最短路
- 八,iOS当UILabel文字不固定时计算label的高度
- python回归分析相关代码-散点图,回归,预测
- 1118. Birds in Forest (25) (并查集,注意顺序)
- 剑指offer经典编程(十)
- 关闭弹框层