Framework篇 - InputManagerSerice 分析整理

本文源代码基于 Android 7.0。 

  • /base/services/core/java/com/android/server/input/InputManagerService.java (IMS)
  • /base/services/core/java/com/android/server/wm/WindowManagerService.java (WMS)
  • /base/services/java/com/android/server/SystemServer.java
  • /base/services/core/jni/com_android_server_input_InputManagerService.cpp
  • /native/services/inputflinger/InputManager.cpp
  • /native/services/inputflinger/InputReader.cpp
  • /native/services/inputflinger/InputDispatcher.cpp
  • /native/libs/input/InputTransport.cpp
  • /base/core/jni/android_view_InputEventReceiver.cpp
  • /base/core/java/android/view/ViewRootImpl.java

这篇文章来分析下 Android 的输入。

 

目录:

  1. Android 的输入系统
  2. InputManagerService 的初始化
  3. InputReader & InputDispatcher 线程
  4. InputChannel
  5. 客户端接收事件

 

 

1. Android 的输入系统

输入事件的源头是位于 /dev/input/ 下的设备节点,而输入系统的终点是由 WMS 管理的某个窗口。最初的输入事件为内核产生的原始事件,最终封装成 KeyEvent 或者 MotionEvent 分发给窗口。流程图如下:

分析一下上图角色:

  • Linux 内核:接收输入设备的中断,并将原始事件数据写入到设备节点。
  • 设备节点:它是 Linux 内核和 IMS 的桥梁,它将原始事件的数据暴露给用户空间,以便 IMS 可以读取。
  • IMS:Android 的一个系统服务,分为 Java 层和 Native 层,Java 层负责与 WMS 通信,而 Native 层则是 InputReader 和 InputDispatcher 这两个输入系统关键组件的运行容器。
  • EventHub:直接访问所有的设备节点,它通过 getEvents() 函数将所有输入系统相关的待处理底层事件返回给使用者,这些事件包括原始输入事件、设备节点的增删等。
  • InputReader:它是 IMS 的关键组件之一,它运行在一个独立的线程,负责管理输入设备的列表与配置,以及进行输入事件的加工处理。它通过线程循环不断地从 EventHub 中用 getEvents() 将事件取出来并进行加工处理。对于设备节点的增删事件,它会更新输入设备列表于配置。对于原始输入事件,InputReader 对其进行翻译、组装、封装为包含了更多信息、更具可读性的输入事件,然后交给 InputDispatcher 进行派发。
  • InputReaderPolicy:它为 InputReader 的事件加工处理提供一些策略配置,例如键盘布局信息等。
  • InputDispatcher:它是 IMS 中的另一个关键组件,它也运行于一个独立的线程中。InputDispatcher 中保管了来自WMS 的所有窗口的信息,其收到来自 InputReader 的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口。
  • InputDispatcherPolicy:它为 InputDispatcher 的派发过程提供策略控制。例如截取某些特定的输入事件用作特殊用途,或者阻止将某些事件派发给目标窗口。一个典型的例子就是 HOME 键被 InputDispatcherPolicy 截取到PhoneWindowManager 中进行处理,并阻止窗口收到 HOME 键按下的事件。
  • WMS:虽说不是输入系统中的一员,但是它却对 InputDispatcher 的正常工作起到了至关重要的作用。当新建窗口时,WMS 为新窗口和 IMS 创建了事件传递所用的通道。另外,WMS 还将所有窗口的信息,包括窗口的可点击区域,焦点窗口等信息,实时地更新到 IMS 的 InputDispatcher 中,使得 InputDispatcher 可以正确地将事件派发到指定的窗口。
  • ViewRootImpl:对于某些窗口,如壁纸窗口、SurfaceView 的窗口来说,窗口即是输入事件派发的终点。而对于其他的如 Activity、对话框等使用了 Android 控件系统的窗口来说,输入事件的终点是控件 (View)。ViewRootImpl 将窗口所接收到的输入事件沿着控件树将事件派发给感兴趣的控件。

总结一下:

内核将原始事件写入到设备节点中,InputReader 不断地通过 EventHub 将原始事件取出来并翻译加工成 Android 输入事件,然后交给 InputDispatcher。InputDispatcher 根据 WMS 提供的窗口信息将事件交给合适的窗口。窗口的 ViewRootImpl 对象再沿着控件树将事件派发给感兴趣的控件。控件对其收到的事件作出响应,更新自己的画面、执行特定的动作。所有这些参与者以 IMS 为核心,构建了 Android 庞大而复杂的输入体系。

 

 

2. InputManagerService 的初始化

InputManagerService 和 ActivityManagerService、WindowManagerService 一样,都是运行在 system_server 进程,也是在 system_server 进程进行初始化的。

 

  • 2.1 SystemServer 启动 InputManagerService
private void startOtherServices() {
	// …
	InputManagerService inputManager = null;
	// 启动InputManagerService
	inputManager = new InputManagerService(context);
    	wm = WindowManagerService.main(context, inputManager,
         mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
         !mFirstBoot, mOnlyCore);
    	ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
	inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
	inputManager.start();
	// …
}

创建完后将自己传给 WindowManagerService,然后调用了 start 函数。

 

  • 2.2 InputManagerService

先看看构造器:

public InputManagerService(Context context) {
    this.mContext = context;
    // 运行在线程"android.display"
    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

    mUseDevInputEventForAudioJack =
            context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
    Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
            + mUseDevInputEventForAudioJack);
    // 初始化native对象,NativeInputManager
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

    LocalServices.addService(InputManagerInternal.class, new LocalService());
}

private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);

里面初始化了 native 对象 (NativeInputManager),再来看看 start():

    public void start() {
        // 启动NativeInputManager对象
        nativeStart(mPtr);

        Watchdog.getInstance().addMonitor(this);

        // 注册触摸点速度和是否显示功能的观察者
        registerPointerSpeedSettingObserver();
        registerShowTouchesSettingObserver();
        registerAccessibilityLargePointerSettingObserver();

        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                updatePointerSpeedFromSettings();
                updateShowTouchesFromSettings();
                updateAccessibilityLargePointerFromSettings();
            }
        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);

        // 更新触摸点的速度
        updatePointerSpeedFromSettings();
        // 是否在屏幕上显示触摸点
        updateShowTouchesFromSettings();
        updateAccessibilityLargePointerFromSettings();
    }

    private static native void nativeStart(long ptr);

 

  • 2.3 com_android_server_input_InputManagerService.cpp

看一下上面的 nativeInit() 和 nativeStart() 的实现。

/** 从InputManagerService的nativeInit调用进来,获取NativeInputManager的指针 */
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    // 获取native消息队列
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    // 创建Native的InputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    // 返回Native对象的指针
    return reinterpret_cast<jlong>(im);
}

nativeInit() 中主要是构造了一个 NativeInputManager 对象,而 NativeInputManager 对象中的 serviceObj 是 Java 层的InputManagerService 对象。来看看 NativeInputManager 的构造器:

/**
 * NativeInputManager构造器
 */
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    // 上层IMS的context
    mContextObj = env->NewGlobalRef(contextObj);
    // 上层InputManagerService对象
    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;

    // 创建EventHub对象
    sp<EventHub> eventHub = new EventHub();
    // 创建InputManager对象,native层
    mInputManager = new InputManager(eventHub, this, this);
}

NativeInputManager 的构造器中创建了 EventHub 对象,并把 EventHub 对象和 NativeInputManager 本身作为参数构造了 InputManager 对象。

nativeStart() 的实现:

/**
 * 该方法的主要功能是启动两个线程:
 *
 *  启动线程“InputReader”
 *  启动线程”InputDispatcher“
 *
 * InputReader:从EventHub取出事件并处理,再交给InputDispatcher
 * InputDispatcher:接收来自InputReader的输入事件,并派发事件到合适的窗口。
 */
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

 

  • 2.4 /native/services/inputflinger/InputManager.cpp

InputManager 的构造器如下:

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);//前面把NativeInputManager的对象传了进来,就是dispatcherPolicy和readerPolicy
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

创建了两个 JNI 层最重要的对象 InputDispatcher,InputReader,initialize() 方法如下:

void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

initialize() 函数把 reader 和 dispatch 对象传进去了,建了两个线程。最后来看看上面 nativeStart() 中 start() 的实现:

status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);

        mDispatcherThread->requestExit();
        return result;
    }

    return OK;
}

 主要工作是启动 InputReader 和 InputDispatcher 这两个线程。

 

  • 2.5 总结

InputManagerService 初始化过程包括:

  • 创建 InputManagerService 服务,并注册到 ServiceManager。
  • 将自己传递给 WindowManagerService。
  • 在构造器构造 EventHub,reader,dispatcher 相关的对象和线程。
  • 启动 InputReader 和 InputDispatcher 这两个线程。

 

 

3. InputReader & InputDispatcher 线程

上面在 nativeStart() 中启动了这两个线程,现在来看看它们的 run() 实现。

 

  • 3.1 InputReader 的 run()
/**
 * 启动线程循环
 * threadLoop返回值true代表的是会不断地循环调用loopOnce()。
 * 另外,如果当返回值为false则会 退出循环。整个过程是不断循环的地调用InputReader的loopOnce()方法,
 * 先来回顾一下InputReader对象构造方法。
 */
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;
    { // acquire lock
        AutoMutex _l(mLock);

        oldGeneration = mGeneration;
        timeoutMillis = -1;

        uint32_t changes = mConfigurationChangesToRefresh;
        if (changes) {
            mConfigurationChangesToRefresh = 0;
            timeoutMillis = 0;
            refreshConfigurationLocked(changes);
        } else if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
        }
    } // release lock

    // 从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        if (count) {
            // 处理事件
            processEventsLocked(mEventBuffer, count);
        }

        if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
                mNextTimeout = LLONG_MAX;
                timeoutExpiredLocked(now);
            }
        }

        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
        // 输入设备发生改变
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    // 发送事件到inputDispatcher
    mQueuedListener->flush();
}

第一个重要的函数 getEvents() 是读取每个设备的数据形成 RawEvent,放入 buffer 中,如果没有输入事件,就 epoll_wait 函数阻塞等待。因此 InputReaderThread 大部分的时间在 epoll_wait 上,有输入设备事件到来则唤醒线程,读数据封装成 RawEvent,放在 mEventBuffer 中然后调用 processEventsLocked()。具体的 getEvents() 函数就不看了,也比较长。这边来看下 processEventsLocked() 的实现。

/**
 * 处理事件
 * 事件处理总共有下几类类型:
 *  DEVICE_ADDED(设备增加)
 *  DEVICE_REMOVED(设备移除)
 *  FINISHED_DEVICE_SCAN(设备扫描完成)
 *  数据事件
 */
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::FINISHED_DEVICE_SCAN:
                handleConfigurationChangedLocked(rawEvent->when);
                break;
            default:
                ALOG_ASSERT(false); // can't happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

这个函数处理 RawEvent 分成两类,一类是设备发生变化的 Event,包括增加,移除,扫描设备结束;另一类是设备自身产生的Event,比如按键的 Event。这类 Event,会从 RawEvent 的 mEventBuffer 中不断读取出来然后调用processEventsForDeviceLocked() 函数处理。

void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex < 0) {
        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
        return;
    }

    InputDevice* device = mDevices.valueAt(deviceIndex);
    if (device->isIgnored()) {
        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }

    // 调用InputDevice.process
    device->process(rawEvents, count);
}

最终经过一系列的包装处理,输出 KeyEvent 和 MotionEvent。然后发送事件到 inputDispatcher (mQueuedListener->flush())。

 

  • 3.2 InputDispatcher.run()
// 启动循环,整个过程不断循环地调用InputDispatcher的dispatchOnce()来分发事件
bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}
/**
 * 线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:
 *
 *  callback:通过回调方法来唤醒;
 *  timeout:到达nextWakeupTime时间,超时唤醒;
 *  wake: 主动调用Looper的wake()方法;
 */
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        AutoMutex _l(mLock);
        // 唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
        mDispatcherIsAliveCondition.broadcast();

        if (!haveCommandsLocked()) {
    		// 当mCommandQueue不为空时处理                                    
		dispatchOnceInnerLocked(&nextWakeupTime);
        }

        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }
    } // release lock

    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    // 进入epoll_wait
    mLooper->pollOnce(timeoutMillis);
}

也就是 InputReader 线程有发送数据后调用 mLooper 的 wake() 函数,唤醒 InputDispatcher 线程来发送给应用线程信息。其中dipatchOnceInnerLocked() 就是分发信息的。

/**
 * 该方法主要功能:

   mDispatchFrozen用于决定是否冻结事件分发工作不再往下执行;
   当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即isAppSwitchDue=true;
   mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间;
   根据EventEntry的type类型分别处理,比如按键调用dispatchKeyLocked分发事件;再根据分发结果来决定是否进入done;
   执行完成(done)的处理:
   根据dropReason(默认NOT_DROPPED不处理)来决定是否丢失事件; dropInboundEventLocked
   释放当前正在处理的事件(即mPendingEvent); releasePendingEventLocked
   关于dispatchKeyLocked分发事件,

   不会执行done过情况:
   当前Event时间小于唤醒时间;
   让policy有机会执行拦截操作;
   调用findFocusedWindowTargetsLocked方法的返回结果是INPUT_EVENT_INJECTION_PENDING, 即targets没有处于Ready状态;
   会执行done的情况:
   该事件需要丢弃, 即dropReason != DROP_REASON_NOT_DROPPED;
   findFocusedWindowTargetsLocked的返回结果不是INPUT_EVENT_INJECTION_PENDING(没有正在处理的事件);
   接下来以按键为例来展开说明, 则进入dispatchKeyLocked.
 */
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    // 当前时间
    nsecs_t currentTime = now();

    // Reset the key repeat timer whenever normal dispatch is suspended while the
    // device is in a non-interactive state.  This is to ensure that we abort a key
    // repeat if the device is just coming out of sleep.
    // 默认值为false
    if (!mDispatchEnabled) {
        // 重置操作
        resetKeyRepeatLocked();
    }

    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
    // 默认值为false
    if (mDispatchFrozen) {
#if DEBUG_FOCUS
        ALOGD("Dispatch frozen.  Waiting some more.");
#endif
        // 当分发被冻结,则不再处理超时和分发事件的工作,直接返回
        return;
    }

    // 优化app切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
    if (mAppSwitchDueTime < *nextWakeupTime) {
        *nextWakeupTime = mAppSwitchDueTime;
    }

    // If we don't already have a pending event, go grab one.
    if (! mPendingEvent) {
        if (mInboundQueue.isEmpty()) {
            if (isAppSwitchDue) {
                resetPendingAppSwitchLocked(false);
                isAppSwitchDue = false;
            }

            // Synthesize a key repeat if appropriate.
            if (mKeyRepeatState.lastKeyEntry) {
                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
                } else {
                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
                    }
                }
            }

            if (!mPendingEvent) {
                // 没有事件需要处理,则直接返回
                return;
            }
        } else {
            // 从mInboundQueue取出头部的事件
            mPendingEvent = mInboundQueue.dequeueAtHead();
            traceInboundQueueLengthLocked();
        }

        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            pokeUserActivityLocked(mPendingEvent);
        }

        // 重置ANR信息
        resetANRTimeoutsLocked();
    }

    ALOG_ASSERT(mPendingEvent != NULL);
    bool done = false;
    DropReason dropReason = DROP_REASON_NOT_DROPPED;
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        dropReason = DROP_REASON_POLICY;
    } else if (!mDispatchEnabled) {
        dropReason = DROP_REASON_DISABLED;
    }

    if (mNextUnblockedEvent == mPendingEvent) {
        mNextUnblockedEvent = NULL;
    }

    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
    }
}

分发不同类型的事件,这边来看看按键事件的分发:

/**
 * 分发按键事件

 在以下场景下,有可能无法分发事件:

 当前时间小于唤醒时间(nextWakeupTime)的情况;
 policy需要提前拦截事件的情况;
 需要drop事件的情况;
 寻找聚焦窗口失败的情况;
 如果成功跳过以上所有情况,则会进入执行事件分发的过程。
 */
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Preprocessing.
    if (! entry->dispatchInProgress) {
        if (entry->repeatCount == 0
                && entry->action == AKEY_EVENT_ACTION_DOWN
                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
                && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
            if (mKeyRepeatState.lastKeyEntry
                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
                resetKeyRepeatLocked();
                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
            } else {
                resetKeyRepeatLocked();
                mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
            }
            mKeyRepeatState.lastKeyEntry = entry;
            entry->refCount += 1;
        } else if (! entry->syntheticRepeat) {
            resetKeyRepeatLocked();
        }

        if (entry->repeatCount == 1) {
            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
        } else {
            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
        }

        entry->dispatchInProgress = true;

        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
    }

    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
        // case1: 当前时间小于唤醒时间,则进入等待状态。
        if (currentTime < entry->interceptKeyWakeupTime) {
            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
                *nextWakeupTime = entry->interceptKeyWakeupTime;
            }
            return false; // wait until next wakeup
        }
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
        entry->interceptKeyWakeupTime = 0;
    }

    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        // case2: 让policy有机会执行拦截操作
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (mFocusedWindowHandle != NULL) {
                commandEntry->inputWindowHandle = mFocusedWindowHandle;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
            return false; // wait for the command to run
        } else {
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        if (*dropReason == DROP_REASON_NOT_DROPPED) {
            *dropReason = DROP_REASON_POLICY;
        }
    }

    // case3: 如果需要丢弃该事件,则执行清理操作
    if (*dropReason != DROP_REASON_NOT_DROPPED) {
        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
        return true;
    }

    // Identify targets.
    Vector<InputTarget> inputTargets;
    // case4: 寻找焦点
    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
            entry, inputTargets, nextWakeupTime);
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }

    setInjectionResultLocked(entry, injectionResult);
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
        return true;
    }

    addMonitoringTargetsLocked(inputTargets);

    // Dispatch the key.
    // 只有injectionResult是成功,才有机会执行分发事件
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

中间经过层层调用,会到达 publishKeyEvent() 函数:

status_t InputPublisher::publishKeyEvent(...) {
    if (!seq) {
        return BAD_VALUE;
    }

    InputMessage msg;
    msg.header.type = InputMessage::TYPE_KEY;
    msg.body.key.seq = seq;
    msg.body.key.deviceId = deviceId;
    msg.body.key.source = source;
    msg.body.key.action = action;
    msg.body.key.flags = flags;
    msg.body.key.keyCode = keyCode;
    msg.body.key.scanCode = scanCode;
    msg.body.key.metaState = metaState;
    msg.body.key.repeatCount = repeatCount;
    msg.body.key.downTime = downTime;
    msg.body.key.eventTime = eventTime;
    //通过InputChannel来发送消息
    return mChannel->sendMessage(&msg);
}

最终调用 InputChannel 发送事件消息。

 

 

4. InputChannel

代码位于 InputTransport.cpp:

status_t InputChannel::sendMessage(const InputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do {
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);

    if (nWrite < 0) {
        int error = errno;
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(),
                msg->header.type, error);
#endif
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (size_t(nWrite) != msgLength) {
#if DEBUG_CHANNEL_MESSAGES
        ALOGD("channel '%s' ~ error sending message type %d, send was incomplete",
                mName.string(), msg->header.type);
#endif
        return DEAD_OBJECT;
    }

#if DEBUG_CHANNEL_MESSAGES
    ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type);
#endif
    return OK;
}

最后会通过 socket 发送。

 

 

5. 客户端接收事件

前面 JNI 层最后调用了 InputChannel 的 sendMessge(),最后是通过 socket 发送的,那我们再来看看客户端的接收。

JNI 层发通过 socket 发信息过来,就会用 epoll 机制唤醒线程,并且处理其事件,代码在 android_view_InputEventReceiver.cpp:

void NativeInputEventReceiver::setFdEvents(int events) {
    if (mFdEvents != events) {
        mFdEvents = events;
        int fd = mInputConsumer.getChannel()->getFd();
        if (events) {
            mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
        } else {
            mMessageQueue->getLooper()->removeFd(fd);
        }
    }
}
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
............
 
    int epollEvents = 0;
    if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
    if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
 
    { // acquire lock
        AutoMutex _l(mLock);
 
        Request request;
        request.fd = fd;
        request.ident = ident;
        request.callback = callback;
        request.data = data;
 
        struct epoll_event eventItem;
        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
        eventItem.events = epollEvents;
        eventItem.data.fd = fd;
 
        ssize_t requestIndex = mRequests.indexOfKey(fd);
        if (requestIndex < 0) {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
            if (epollResult < 0) {
                ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
                return -1;
            }
            mRequests.add(fd, request);
        } else {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);//将当前fd加入到epoll中
            if (epollResult < 0) {
                ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
                return -1;
            }
            mRequests.replaceValueAt(requestIndex, request);
        }
    } // release lock
    return 1;
}

addFd() 函数将参数 fd 加入 epoll,然后在 mRequests 列表中加入一个 Request 对象,这个对象的 events 成员带有 EPOLLIN 标记,然后它的 callBack 成员变量指向 NativeInputEventReceiver。以前分析 looper 机制的时候知道,线程处理消息循环会调用looper 的 poolOnce() 函数,而这个函数又会调用 pollInner 函数:

int Looper::pollInner(int timeoutMillis) {
..........
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);//事件到来
..........
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {//管道事件,就是调用wakeup函数的
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
            }
        } else {//其它事件,就包括InputChannel的socket
            ssize_t requestIndex = mRequests.indexOfKey(fd);//获取request的index
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
                pushResponse(events, mRequests.valueAt(requestIndex));//加入mResponses列表
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }
............
 
    // Invoke all response callbacks.处理所有的mResponses元素
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
            int callbackResult = response.request.callback->handleEvent(fd, events, data);//调用回调事件
            if (callbackResult == 0) {
                removeFd(fd);
            }
            // Clear the callback reference in the response structure promptly because we
            // will not clear the response vector itself until the next poll.
            response.request.callback.clear();
            result = POLL_CALLBACK;
        }
    }
    return result;
}

把客户端 socket 的 fd 加入客户端线程消息机制中的 epoll,当有事件过来,最总会调用回调。也就会调用NativeInputEventReceiver::handleEvent() 函数:

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
..........
 
    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? 1 : 0;
    }
	..........
}

consumeEvents() 函数如下,先读取 socket 的信息然后反调 Java 层 WindowInputEventReceiver 的 dispatchInputEvent() 方法,这是父类的方法,然后再到子类 WindowInputEventReceiver 的 onInputEvent() 方法:

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
......
    for (;;) {
	    uint32_t seq;
        InputEvent* inputEvent;
        status_t status = mInputConsumer.consume(&mInputEventFactory,//读取InputChannel的socket信息
                consumeBatches, frameTime, &seq, &inputEvent);
		........
		      if (inputEventObj) {//反调java层的WindowInputEventReceiver的dispatchInputEvent方法
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
.....
}

这就到了 ViewRootImpl 的内部类 WindowInputEventReceiver.onInputEvent():

    final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

        @Override
        public void onInputEvent(InputEvent event) {
            enqueueInputEvent(event, this, 0, true);
        }

        @Override
        public void onBatchedInputEventPending() {
            if (mUnbufferedInputDispatch) {
                super.onBatchedInputEventPending();
            } else {
                scheduleConsumeBatchedInput();
            }
        }

        @Override
        public void dispose() {
            unscheduleConsumeBatchedInput();
            super.dispose();
        }
    }
  void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
        adjustInputEventForCompatibility(event);
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
        QueuedInputEvent last = mPendingInputEventTail;
        if (last == null) {
            mPendingInputEventHead = q;
            mPendingInputEventTail = q;
        } else {
            last.mNext = q;
            mPendingInputEventTail = q;
        }
        mPendingInputEventCount += 1;
        Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                mPendingInputEventCount);

        if (processImmediately) {
            // 收到InputDispatcher的事件分发,开始处理分发事件
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
    }
    /**
     * InputDispatcher线程调用InputPublisher的publishKeyEvent向UI主线程发送input事件;
     *
     * UI主线程接收到该事件后,调用InputConsumer的consumeEvents来处理该事件, 一路执行到ViewRootImpl.deliverInputEvent()方法;
     *
     * UI主线程经过一系列的InputStage来处理, 当事件分发完成,则会执行finishInputEvent()方法.
     * 再进一步调用InputConsumer::sendFinishedSignal 告知InputDispatcher线程该时事件已处理完成.
     *
     * InputDispatcher线程收到该事件后, 执行InputDispatcher::handleReceiveCallback();
     * 最终会调用doDispatchCycleFinishedLockedInterruptible()方法 ,将dispatchEntry事件从等待队列(waitQueue)中移除.
     */
    void doProcessInputEvents() {
        // Deliver all pending input events in the queue.
        while (mPendingInputEventHead != null) {
            QueuedInputEvent q = mPendingInputEventHead;
            mPendingInputEventHead = q.mNext;
            if (mPendingInputEventHead == null) {
                mPendingInputEventTail = null;
            }
            q.mNext = null;

            mPendingInputEventCount -= 1;
            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                    mPendingInputEventCount);

            long eventTime = q.mEvent.getEventTimeNano();
            long oldestEventTime = eventTime;
            if (q.mEvent instanceof MotionEvent) {
                MotionEvent me = (MotionEvent)q.mEvent;
                if (me.getHistorySize() > 0) {
                    oldestEventTime = me.getHistoricalEventTimeNano(0);
                }
            }
            mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);

            // 分发事件
            deliverInputEvent(q);
        }

        // We are done processing all input events that we can process right now
        // so we can clear the pending flag immediately.
        if (mProcessInputEventsScheduled) {
            mProcessInputEventsScheduled = false;
            mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
        }
    }
    /**
     * 经过一系列的InputStage调用, 最终会分发到真正需要处理该事件的窗口. 当处理完后会调用finishInputEvent()
     * @param q
     */
    private void deliverInputEvent(QueuedInputEvent q) {
        Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
                q.mEvent.getSequenceNumber());
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
        }

        InputStage stage;
        if (q.shouldSendToSynthesizer()) {
            stage = mSyntheticInputStage;
        } else {
            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
        }

        if (stage != null) {
            stage.deliver(q);
        } else {
            finishInputEvent(q);
        }
    }

经过一系列的 InputStage 调用,最终会分发到真正需要处理该事件的窗口,当处理完后会调用 finishInputEvent()。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
.NET Framework 4.5-x86-x64是一种由微软公司开发的应用程序框架。它提供了一种创建和运行各种类型应用程序的环境,包括桌面应用程序、Web应用程序和移动应用程序。 使用.NET Framework 4.5-x86-x64,开发人员可以利用其强大的功能来创建功能丰富、高性能的应用程序。它提供了一系列的类库和工具,可以轻松地处理各种任务,例如图形处理、数据访问和网络通信。它还支持多种编程语言,包括C#、Visual Basic和F#等,使开发人员可以按照自己的喜好选择最适合自己的编程语言。 对于应用程序的部署,.NET Framework 4.5-x86-x64提供了高度灵活性和可移植性。开发人员可以将应用程序打包成自包含的可执行文件,方便用户在不同计算机上安装和运行。此外,.NET Framework 4.5-x86-x64还支持与现有系统和应用程序的集成,使应用程序能够与其他软件进行无缝协作。 作为一个跨平台的框架,.NET Framework 4.5-x86-x64可以在多个操作系统上运行,包括Windows、Linux和macOS等。这为开发人员提供了更大的灵活性和选择性,使他们可以根据不同的需求和目标平台选择最适合的环境。 总之,.NET Framework 4.5-x86-x64是一个功能强大、灵活性高的应用程序框架,它为开发人员提供了丰富的工具和资源,使他们能够轻松地创建出各种类型的应用程序,并在不同平台上进行部署和运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值