Android 12 Input系统理解
参考文献: Input系统—启动篇 Input系统—InputReader线程 Input系统—InputDispatcher线程 Input系统—UI线程 Input系统—事件处理全过程
一、Input系统-事件处理过程
frameworks/native/services/inputflinger/
- InputDispatcher.cpp
- InputReader.cpp
- InputManager.cpp
- EventHub.cpp
- InputListener.cpp
frameworks/native/libs/input/
- InputTransport.cpp
- Input.cpp
- InputDevice.cpp
- Keyboard.cpp
- KeyCharacterMap.cpp
- IInputFlinger.cpp
frameworks/base/services/core/
- java/com/android/server/input/InputManagerService.java
- jni/com_android_server_input_InputManagerService.cpp
1. Input系统—概述
用户触摸屏幕(TP)或者物理按键,触发的是硬件驱动。驱动将事件写入到输入设备节点;接着输入系统将设备节点经过每一层封装后,成为KeyEvent或者MotionEvent;最后,给到对应窗口(Window)消费该事件。
Input模块主要组成:
- Native层的InputReader负责从EventHub取出事件并处理,再交给InputDispatcher
- Native层的InputDispatcher接收来自InputReader的输入事件,并记录WMS的窗口信息,用于派发事件到合适的窗口
- Java层的InputManagerService跟WMS交互,WMS记录所有窗口信息,并同步更新到IMS,为InputDispatcher正确派发事件到ViewRootImpl提供保障
Input相关动态库:
- libinputflinger.so:frameworks/native/services/inputflinger/
- libinputservice.so:frameworks/base/libs/input/
- libinput.so: frameworks/native/libs/input/
2.Input系统—启动过程
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
frameworks/native/services/inputflinger/InputManager.cpp
#SystemServer.java
├──startOtherServices()
└──inputManager = new InputManagerService(context, mActivityManagerService);//InputManagerService初始化
| #InputManagerService.java
| └──mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
| #com_android_server_input_InputManagerService.cpp
| ├──nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj)
| └──NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());
| └──InputManager* im = new InputManager(this, this);
| #InputManager.cpp
| └──mDispatcher = createInputDispatcher(dispatcherPolicy);//创建InputDispatcher对象
| └──mClassifier = new InputClassifier(mDispatcher);//创建InputClassifier对象
| └──mReader = createInputReader(readerPolicy, mClassifier);//创建InputReader对象
└──inputManager.start();
#com_android_server_input_InputManagerService.cpp
└──nativeStart(mPtr);
#InputManager.cpp
├──nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr)
└──status_t result = mDispatcher->start();
└──result = mReader->start();
2.1#SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
inputManager = new InputManagerService(context, mActivityManagerService);//创建InputManagerService对象
...
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);//将InputManagerService与WindowManagerService绑定
...
ServiceManager.addService(Context.INPUT_SERVICE, inputManager, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
...
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());//设置Input回调
inputManager.start();//启动Input系统
}
2.2#InputManagerService.java
public InputManagerService(Context context, ActivityManagerService ams) {
...
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//运行在线程"android.display"
...
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
...
}
2.3#nativeInit
<-com_android_server_input_InputManagerService.cpp>
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);//获取native消息队列
...
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());
im->incStrong(0);
eturn reinterpret_cast<jlong>(im);
}
2.4#NativeInputManager
<-com_android_server_input_InputManagerService.cpp>
NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {
...
mServiceObj = env->NewGlobalRef(serviceObj);//上层IMS对象
...
InputManager* im = new InputManager(this, this);// 创建InputManager对象
...
}
2.5#InputManager
<-InputManager.cpp>
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = new InputClassifier(mDispatcher);
mReader = createInputReader(readerPolicy, mClassifier);
}
2.6#InputDispatcher
<-InputDispatcher.cpp>
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
// mInTouchMode will be initialized by the WindowManager to the default device config.
// To avoid leaking stack in case that call never comes, and for tests,
// initialize it here anyways.
mInTouchMode(true),
mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
mLatencyAggregator(),
mLatencyTracker(&mLatencyAggregator),
mCompatService(getCompatService()) {
mLooper = new Looper(false);//创建Looper对象
mReporter = createInputReporter();//创建InputReporter对象
mKeyRepeatState.lastKeyEntry = nullptr;
policy->getDispatcherConfiguration(&mConfig);//获取分发超时参数
}
该方法主要工作:
- 创建属于自己线程的Looper对象;
- 超时参数来自于IMS,参数默认值keyRepeatTimeout = 500,keyRepeatDelay = 50
2.7#InputReader
<-InputReader.cpp>
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
mLedMetaState(AMETA_NUM_LOCK_ON),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);//创建输入监听对象
{ // acquire lock
std::scoped_lock _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
2.8#IMS.start()
<-InputManagerService.java>
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
registerPointerSpeedSettingObserver();//注册触摸点速度观察者
registerShowTouchesSettingObserver();//注册是否显示功能的观察者
registerAccessibilityLargePointerSettingObserver();
registerLongPressTimeoutObserver();
registerMaximumObscuringOpacityForTouchSettingObserver();
registerBlockUntrustedTouchesModeSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("user switched");
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();//更新触摸点的速度
updateShowTouchesFromSettings();//更新是否在屏幕上显示触摸点状态
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("just booted");
updateMaximumObscuringOpacityForTouchFromSettings();
updateBlockUntrustedTouchesModeFromSettings();
}
2.8#nativeStart
<-com_android_server_input_InputManagerService.cpp>
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();//调用InputManager.cpp中start()
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
2.9#InputManager.start
<-InputManager.cpp>
status_t InputManager::start() {
status_t result = mDispatcher->start();//启动InputDispatcher线程
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReader->start();//启动InputReader线程
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;//“OK”代表成功,启动成功
}
3. Input系统—InputReader线程
frameworks/native/services/inputflinger/reader/InputReader.cpp
frameworks/native/services/inputflinger/reader/EventHub.cpp
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/services/inputflinger/reader/InputDevice.cpp
frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
frameworks/native/services/inputflinger/InputListener.cpp
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
system/core/libutils/Looper.cpp
#InputReader.cpp
├──start()
└──mThread = std::make_unique<InputThread>( "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
└──loopOnce()
| └──size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
| | #EventHub.cpp
| | ├──getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize)//通过EventHub(监听目录/dev/input)读取事件放入mEventBuffer, 再将事件input_event转换为RawEvent
| | └──scanDevicesLocked()
| | └──scanDirLocked(const std::string& dirname)
| | └──openDeviceLocked(const std::string& devicePath)
| | └──addDeviceLocked(std::unique_ptr<Device> device)
| └──processEventsLocked(mEventBuffer, count);//对事件进行加工, 转换RawEvent -> NotifyKeyArgs(NotifyArgs)
| | └──if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT)
| | | └──processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count)
| | | └──device->process(rawEvents, count);
| | | #InputDevice.cpp
| | | ├──process(const RawEvent* rawEvents, size_t count)
| | | └──mapper.process(rawEvent);//列举KeyboardInputMapper作为例子
| | | #KeyboardInputMapper.cpp
| | | ├──process(const RawEvent* rawEvent)
| | | └──processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,int32_t usageCode)
| | | └──getListener()->notifyKey(&args);
| | | #InputListener.cpp
| | | ├──notifyKey(const NotifyKeyArgs* args)
| | | └──mArgsQueue.push_back(new NotifyKeyArgs(*args));
| | └──else
| | └──addDeviceLocked(rawEvent->when, rawEvent->deviceId);
| | └──std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
| | └──device->addEventHubDevice(eventHubId);
| | #InputDevice.cpp
| | ├──addEventHubDevice(int32_t eventHubId, bool populateMappers)
| | └──添加各类输入设备
| └──mQueuedListener->flush();//将事件发送到InputDispatcher线程
| #InputListener.cpp
| ├──flush()
| └──notify(const sp<InputListenerInterface>& listener)
| └──listener->notifyKey(this);
| #InputDispatcher.cpp
| ├──notifyKey(const NotifyKeyArgs* args)
| └──mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
| | #com_android_server_input_InputManagerService.cpp
| | ├──interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags)
| | └── wmActions = env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptKeyBeforeQueueing, keyEventObj, policyFlags);
| └──mPolicy->filterInputEvent(&event, policyFlags)
| | #com_android_server_input_InputManagerService.cpp
| | ├──filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags)
| | └── jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,//当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
| └──needWake = enqueueInboundEventLocked(std::move(newEntry));
| | #InputDispatcher.cpp
| | ├──enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry)
| | └──shouldPruneInboundQueueLocked(const MotionEntry& motionEntry)
| | └──sp<InputWindowHandle> touchedWindowHandle =findTouchedWindowAtLocked(displayId, x, y, nullptr);//查询触摸的窗口
| | └──std::vector<TouchedMonitor> gestureMonitors = findTouchedGestureMonitorsLocked(displayId, {});//查询可触摸的手势
| └──mLooper->wake();//唤起InputDispatcher线程
| #Looper.cpp
| ├──wake()
| └──ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
└──mEventHub->wake(); //唤起EventHub
#EventHub.cpp
├──wake()
└──nWrite = write(mWakeWritePipeFd, "W", 1);
3.1#start()
<-InputReader.cpp>
status_t InputReader::start() {
if (mThread) {//mThread不为空,InputReader已存在
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
3.2#loopOnce()
<-InputReader.cpp>
void InputReader::loopOnce() {
...
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);//从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
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;
inputDevices = getInputDevicesLocked();
}
} // release lock
...
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {//输入设备发生改变
mPolicy->notifyInputDevicesChanged(inputDevices);
}
mQueuedListener->flush();//发送事件到InputDispatcher
}
3.2#getEvents()
<-EventHub.cpp>
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
...
for (;;) {
...
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();//扫描设备
mNeedToSendFinishedDeviceScan = true;
}
...
while (mPendingEventIndex < mPendingEventCount) {
...
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];//从mPendingEventItems读取事件项
...
if (eventItem.data.fd == mWakeReadPipeFd) {
if (eventItem.events & EPOLLIN) {
ALOGV("awoken after wake()");
awoken = true;
char wakeReadBuffer[16];
ssize_t nRead;
do {
nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));//从wakeReadBuffer中读取事件
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
} else {
ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
eventItem.events);
}
continue;
}
...
// This must be an input event
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //从设备不断读取事件,放入到readBuffer
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
deviceChanged = true;
closeDeviceLocked(*device);
}
...
}else{
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];//获取readBuffer的数据
event->when = processEventTimestamp(iev);//将input_event信息, 封装成RawEvent
event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
if (capacity == 0) {
// The result buffer is full. Reset the pending event index
// so we will try to read the device again on the next iteration.
mPendingEventIndex -= 1;
break;
}
}
...
}
...
}
...
mLock.unlock(); // release lock before poll
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);//等待input事件的到来
mLock.lock(); // reacquire lock after poll
...
}
...
return event - buffer; //返回所读取的事件个数
}
EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点。
3.3设备扫描
<-EventHub.cpp>
void EventHub::scanDevicesLocked() {
status_t result = scanDirLocked(DEVICE_PATH);//DEVICE_PATH="/dev/input"
if (result < 0) {
ALOGE("scan dir failed for %s", DEVICE_PATH);
}
if (isV4lScanningEnabled()) {
result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
if (result != OK) {
ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
}
}
if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
createVirtualKeyboardLocked();
}
}
status_t EventHub::scanDirLocked(const std::string& dirname) {
for (const auto& entry : std::filesystem::directory_iterator(dirname)) {//读取/dev/input/目录下所有的设备节点
openDeviceLocked(entry.path());//打开相应的设备节点
}
return 0;
}
void EventHub::openDeviceLocked(const std::string& devicePath) {
...
int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);//打开设备文件
InputDeviceIdentifier identifier;
//获取设备名称
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name = buffer;
}
...
// Get device identifier.
struct input_id inputId;
if (ioctl(fd, EVIOCGID, &inputId)) {
ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return;
}
identifier.bus = inputId.bustype;
identifier.product = inputId.product;
identifier.vendor = inputId.vendor;
identifier.version = inputId.version;
// Get device physical location.
if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.location = buffer;
}
// Get device unique id.
if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.uniqueId = buffer;
}
// Fill in the descriptor.
assignDescriptorLocked(identifier);
...
// Load the configuration file for the device.
device->loadConfigurationLocked();
...
addDeviceLocked(std::move(device));
}
void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);
mOpeningDevices.push_back(std::move(device));
}
3.4 设备增加
3.4.1#processEventsLocked()
<-InputReader.cpp>
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: %zu Count: %zu", 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;
}
}
3.4.2#addDeviceLocked
<-InputReader.cpp>
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
if (mDevices.find(eventHubId) != mDevices.end()) {
ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
return;//已添加的相同设备则不再添加
}
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
device->configure(when, &mConfig, 0);
device->reset(when);
...
mDevices.emplace(eventHubId, device);
// Add device to device to EventHub ids map.
const auto mapIt = mDeviceToEventHubIdsMap.find(device);
if (mapIt == mDeviceToEventHubIdsMap.end()) {
std::vector<int32_t> ids = {eventHubId};
mDeviceToEventHubIdsMap.emplace(device, ids);
} else {
mapIt->second.push_back(eventHubId);
}
...
}
std::shared_ptr<InputDevice> InputReader::createDeviceLocked( int32_t eventHubId, const InputDeviceIdentifier& identifier) {
...
std::shared_ptr<InputDevice> device;
if (deviceIt != mDevices.end()) {
device = deviceIt->second;
} else {
int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(), identifier);
}
device->addEventHubDevice(eventHubId);
return device;
}
3.4.3#addEventHubDevice
<-InputDevice.cpp>
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
...
// Keyboard-like devices.
uint32_t keyboardSource = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
if (classes.test(InputDeviceClass::KEYBOARD)) {
keyboardSource |= AINPUT_SOURCE_KEYBOARD;
}
if (classes.test(InputDeviceClass::ALPHAKEY)) {
keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
}
if (classes.test(InputDeviceClass::DPAD)) {
keyboardSource |= AINPUT_SOURCE_DPAD;
}
if (classes.test(InputDeviceClass::GAMEPAD)) {
keyboardSource |= AINPUT_SOURCE_GAMEPAD;
}
//添加键盘类设备InputMapper
if (keyboardSource != 0) {
mappers.push_back(
std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
}
//添加鼠标类设备InputMapper
if (classes.test(InputDeviceClass::CURSOR)) {
mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
}
//添加触摸屏设备InputMapper
if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
} else if (classes.test(InputDeviceClass::TOUCH)) {
mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
}
// Joystick-like devices.
if (classes.test(InputDeviceClass::JOYSTICK)) {
mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
}
// Motion sensor enabled devices.
if (classes.test(InputDeviceClass::SENSOR)) {
mappers.push_back(std::make_unique<SensorInputMapper>(*contextPtr));
}
// External stylus-like devices.
if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
}
// insert the context into the devices set
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
// Must change generation to flag this device as changed
bumpGeneration();
}
3.5 事件处理
3.5.1#processEventsForDeviceLocked
<-InputReader.cpp>
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count) {
auto deviceIt = mDevices.find(eventHubId);
if (deviceIt == mDevices.end()) {
ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
return;
}
std::shared_ptr<InputDevice>& device = deviceIt->second;
if (device->isIgnored()) {
// ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
device->process(rawEvents, count);
}
3.5.2#process
<-InputDevice.cpp>
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
#if DEBUG_RAW_EVENTS
ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
#endif
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
#if DEBUG_RAW_EVENTS
ALOGD("Recovered from input event buffer overrun.");
#endif
} else {
#if DEBUG_RAW_EVENTS
ALOGD("Dropped input event while waiting for next input sync.");
#endif
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);//调用具体mapper来处理,见【3.6】按键事件处理
});
}
--count;
}
}
3.6按键事件处理
3.6.1#KeyboardInputMapper.process
<-KeyboardInputMapper.cpp>
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
mCurrentHidUsage = 0;
if (isKeyboardOrGamepadKey(scanCode)) {
processKey(rawEvent->when, rawEvent->readTime, rawEvent->value != 0, scanCode,usageCode);//获取所对应的KeyCode
}
break;
}
case EV_MSC: {
if (rawEvent->code == MSC_SCAN) {
mCurrentHidUsage = rawEvent->value;
}
break;
}
case EV_SYN: {
if (rawEvent->code == SYN_REPORT) {
mCurrentHidUsage = 0;
}
}
}
}
void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,int32_t usageCode) {
if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,&policyFlags)) {
keyCode = AKEYCODE_UNKNOWN;
keyMetaState = mMetaState;
policyFlags = 0;
}
if (down) {
// Rotate key codes according to orientation if needed.
if (mParameters.orientationAware) {
keyCode = rotateKeyCode(keyCode, getOrientation());
}
// Add key down.
ssize_t keyDownIndex = findKeyDown(scanCode);
if (keyDownIndex >= 0) {
// key repeat, be sure to use same keycode as before in case of rotation
keyCode = mKeyDowns[keyDownIndex].keyCode;
} else {
// key down
if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
return;
}
if (policyFlags & POLICY_FLAG_GESTURE) {
getDeviceContext().cancelTouch(when, readTime);
}
KeyDown keyDown;
keyDown.keyCode = keyCode;
keyDown.scanCode = scanCode;
mKeyDowns.push_back(keyDown);
}
mDownTime = when;//记录按下时间点
} else {
// Remove key down.
ssize_t keyDownIndex = findKeyDown(scanCode);
if (keyDownIndex >= 0) {
// key up, be sure to use same keycode as before in case of rotation
keyCode = mKeyDowns[keyDownIndex].keyCode;
mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);//键抬起操作,则擦除按下事件
} else {
// key was not actually down
ALOGI("Dropping key up from device %s because the key was not down. " "keyCode=%d, scanCode=%d", getDeviceName().c_str(), keyCode, scanCode);
return;
}
}
nsecs_t downTime = mDownTime;
...
//创建NotifyKeyArgs对象, when记录eventTime, downTime记录按下时间;
NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
getDisplayId(), policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
getListener()->notifyKey(&args);//通知key事件
}
3.6.2#QueuedInputListener.notifyKey
<-InputListener.cpp>
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyKeyArgs(*args));
}
mArgsQueue的数据类型为Vector<NotifyArgs*>,将该key事件压人该栈顶。 到此,整个事件加工完成, 再然后就是将事件发送给InputDispatcher线程. 接下来,再回调InputReader的loopOnce过程, 可知当执行完processEventsLocked()过程, 然后便开始执行mQueuedListener->flush()过程, 如下文.
3.7#QueuedListener
3.7.1#flush()
<-InputListener.cpp>
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener);//mInnerListener是InputDispatcher对象
delete args;
}
mArgsQueue.clear();
}
遍历整个mArgsQueue数组, 在input架构中NotifyArgs的实现子类主要有以下几类:
- NotifyConfigurationChangedArgs
- NotifyKeyArgs
- NotifyMotionArgs
- NotifySwitchArgs
- NotifyDeviceResetArgs
接着3.6节,可知此处是NotifyKeyArgs对象
3.7.2#NotifyKeyArgs.notify
<-InputListener.cpp>
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this);
}
3.7.3#InputDispatcher.notifyKey
<-InputDispatcher.cpp>
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
...
KeyEvent event;
event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
args->downTime, args->eventTime);//初始化KeyEvent对象
...
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
std::to_string(t.duration().count()).c_str());
}
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {//mPolicy是指NativeInputManager对象
return; // event was consumed by the filter
}
mLock.lock();
}
std::unique_ptr<KeyEntry> newEntry =
std::make_unique<KeyEntry>(args->id, args->eventTime, args->deviceId, args->source,
args->displayId, policyFlags, args->action, flags,
keyCode, args->scanCode, metaState, repeatCount,
args->downTime);//创建KeyEntry对象
needWake = enqueueInboundEventLocked(std::move(newEntry));//将KeyEntry放入队列
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake();//唤醒InputDispatcher线程
}
}
该方法的主要功能:
- 调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:
- IMS.interceptKeyBeforeQueueing
- InputMonitor.interceptKeyBeforeQueueing (继承IMS.WindowManagerCallbacks)
- PhoneWindowManager.interceptKeyBeforeQueueing (继承WindowManagerPolicy)
- 当mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件;当返回值为false则过滤该事件,不再往下分发;
- 生成KeyEvent,并调用enqueueInboundEventLocked,将该事件加入到InputDispatcherd的成员变量mInboundQueue。
3.7.4#interceptKeyBeforeQueueing
<-com_android_server_input_InputManagerService.cpp>
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
...
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,
gServiceClassInfo.interceptKeyBeforeQueueing,//调用Java层的IMS.interceptKeyBeforeQueueing
keyEventObj, policyFlags);
...
} else {
...
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
...
}
}
3.7.5#filterInputEvent
<-com_android_server_input_InputManagerService.cpp>
bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
jobject inputEventObj;
JNIEnv* env = jniEnv();
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<const KeyEvent*>(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION:
inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
static_cast<const MotionEvent*>(inputEvent));
break;
default:
return true; // dispatch the event normally
}
if (!inputEventObj) {
ALOGE("Failed to obtain input event object for filterInputEvent.");
return true; // dispatch the event normally
}
// The callee is responsible for recycling the event.
jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,//当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
inputEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
pass = true;
}
env->DeleteLocalRef(inputEventObj);
return pass;
}
3.7.6#enqueueInboundEventLocked
<-InputDispatcher.cpp>
bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
...
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.
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
if (isAppSwitchKeyEvent(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;
}
case EventEntry::Type::MOTION: {
if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(entry))) {
mNextUnblockedEvent = mInboundQueue.back();
needWake = true;
}
break;
}
case EventEntry::Type::FOCUS: {
LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked");
break;
}
case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR:
case EventEntry::Type::POINTER_CAPTURE_CHANGED:
case EventEntry::Type::DRAG: {
// nothing to do
break;
}
}
return needWake;
}
bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) {
...
if (isPointerDownEvent && mAwaitedFocusedApplication != nullptr) {
int32_t displayId = motionEntry.displayId;
int32_t x = static_cast<int32_t>(
motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = static_cast<int32_t>(
motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
sp<InputWindowHandle> touchedWindowHandle =findTouchedWindowAtLocked(displayId, x, y, nullptr);//查询可触摸的窗口
if (touchedWindowHandle != nullptr &&
touchedWindowHandle->getApplicationToken() !=
mAwaitedFocusedApplication->getApplicationToken()) {
// User touched a different application than the one we are waiting on.
ALOGI("Pruning input queue because user touched a different application while waiting "
"for %s",
mAwaitedFocusedApplication->getName().c_str());
return true;
}
/ / Alternatively, maybe there's a gesture monitor that could handle this event
std::vector<TouchedMonitor> gestureMonitors = findTouchedGestureMonitorsLocked(displayId, {});//查询可触摸的手势
for (TouchedMonitor& gestureMonitor : gestureMonitors) {
sp<Connection> connection =
getConnectionLocked(gestureMonitor.monitor.inputChannel->getConnectionToken());
if (connection != nullptr && connection->responsive) {
// This monitor could take more input. Drop all events preceding this
// event, so that gesture monitor could get a chance to receive the stream
ALOGW("Pruning the input queue because %s is unresponsive, but we have a "
"responsive gesture monitor that may handle the event",
mAwaitedFocusedApplication->getName().c_str());
return true;
}
}
}
...
}
sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
int32_t y, TouchState* touchState,
bool addOutsideTargets,
bool addPortalWindows,
bool ignoreDragWindow) {
...
// Traverse windows from front to back to find touched window.
const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId);
for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
continue;
}
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId == displayId) {
auto flags = windowInfo->flags;
if (windowInfo->visible) {
if (!flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE)) {
bool isTouchModal = !flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE) &&
!flags.test(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
int32_t portalToDisplayId = windowInfo->portalToDisplayId;
if (portalToDisplayId != ADISPLAY_ID_NONE &&
portalToDisplayId != displayId) {
if (addPortalWindows) {
// For the monitoring channels of the display.
touchState->addPortalWindow(windowHandle);
}
return findTouchedWindowAtLocked(portalToDisplayId, x, y, touchState,
addOutsideTargets, addPortalWindows);
}
// Found window.
return windowHandle;//找到目标窗口
}
}
if (addOutsideTargets && flags.test(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) {
touchState->addOrUpdateWindow(windowHandle,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
BitSet32(0));
}
}
}
}
return nullptr;
}
此处mWindowHandles的赋值过程是由Java层的InputMonitor.setInputWindows(),经过JNI调用后进入InputDispatcher::setInputWindows()方法完成. 进一步说, 就是WMS执行addWindow()过程或许UI改变等场景,都会触发该方法的修改.
3.7.7#Looper.wake
<-Looper.cpp>
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ wake", this);
#endif
uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
LOG_ALWAYS_FATAL("Could not write wake signal to fd %d (returned %zd): %s",
mWakeEventFd.get(), nWrite, strerror(errno));
}
}
}
【3.7】小节过程会调用enqueueInboundEventLocked()方法来决定是否需要将数字1写入句柄mWakeEventFd来唤醒InputDispatcher线程. 满足唤醒的条件:
- 执行enqueueInboundEventLocked方法前,mInboundQueue队列为空,执行完必然不再为空,则需要唤醒分发线程;
- 当事件类型为key事件,且发生一对按下和抬起操作,则需要唤醒;
- 当事件类型为motion事件,且当前可触摸的窗口属于另一个应用,则需要唤醒.
3.8 小结
InputReader整个过程涉及多次事件封装转换,其主要工作核心是以下三大步骤:
- getEvents:通过EventHub(监听目录/dev/input)读取事件放入mEventBuffer,而mEventBuffer是一个大小为256的数组, 再将事件input_event转换为RawEvent;
- processEventsLocked: 对事件进行加工, 转换RawEvent -> NotifyKeyArgs(NotifyArgs)
- QueuedListener->flush:将事件发送到InputDispatcher线程, 转换NotifyKeyArgs -> KeyEntry(EventEntry)
InputReader线程不断循环地执行InputReader.loopOnce(), 每次处理完生成的是EventEntry(比如KeyEntry, MotionEntry), 接下来的工作就交给InputDispatcher线程。
4. Input系统—InputDispatcher线程
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/libs/input/InputTransport.cpp
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
#InputDispatcher.cpp
├──start()
└──mThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
└──dispatchOnce()
└──dispatchOnceInnerLocked(&nextWakeupTime);
| └──done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
| | └──findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry& entry, std::vector<InputTarget>& inputTargets,nsecs_t* nextWakeupTime)
| | | └──resetNoFocusedWindowTimeoutLocked();
| | | └──addWindowTargetLocked(focusedWindowHandle, InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,BitSet32(0), inputTargets);//成功找到目标窗口,添加到目标窗口
| | └──addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
| | └──dispatchEventLocked(currentTime, entry, inputTargets);
| | └──updateInteractionTokensLocked(*eventEntry, inputTargets);
| | └──pokeUserActivityLocked(*eventEntry);//向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
| | | └──std::unique_ptr<CommandEntry> commandEntry =std::make_unique<CommandEntry>(&InputDispatcher::doPokeUserActivityLockedInterruptible);
| | | | └── mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType,commandEntry->displayId);
| | | | #com_android_server_input_InputManagerService.cpp
| | | | ├──pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId)
| | | | └──android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
| | | | #com_android_server_power_PowerManagerService.cpp
| | | | ├──env->CallVoidMethod(gPowerManagerServiceObj,gPowerManagerServiceClassInfo.userActivityFromNative,nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
| | | | └──android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,int32_t displayId)
| | | | #PowerManagerService.java
| | | | ├──userActivityFromNative(long eventTime, int event, int displayId, int flags)
| | | | └──userActivityInternal(int displayId, long eventTime, int event, int flags,int uid)
| | | └──postCommandLocked(std::move(commandEntry));
| | | └──mCommandQueue.push_back(std::move(commandEntry));// 将命令加入mCommandQueue队尾
| | └──prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);//找到目标连接
| | └──enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
| | └──enqueueDispatchEntryLocked(const sp<Connection>& connection,std::shared_ptr<EventEntry> eventEntry,const InputTarget& inputTarget,int32_t dispatchMode)
| | | └──connection->outboundQueue.push_back(dispatchEntry.release());//添加到outboundQueue队尾
| | └──startDispatchCycleLocked(currentTime, connection);
| | #InputTransport.cpp
| | ├──status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
| | | dispatchEntry->resolvedEventId, keyEntry.deviceId,
| | | keyEntry.source, keyEntry.displayId,
| | | std::move(hmac), dispatchEntry->resolvedAction,
| | | dispatchEntry->resolvedFlags, keyEntry.keyCode,
| | | keyEntry.scanCode, keyEntry.metaState,
| | | keyEntry.repeatCount, keyEntry.downTime,
| | | keyEntry.eventTime);//发布Key事件
| | └──return mChannel->sendMessage(&msg);
| └──releasePendingEventLocked();//释放pending事件
└──runCommandsLockedInterruptible()
└──mLooper->pollOnce(timeoutMillis);//进入epoll_wait
4.1#start()
<-InputDispatcher.cpp>
status_t InputDispatcher::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
4.2#dispatchOnce()
<-InputDispatcher.cpp>
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();//唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
// 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;
}
// If we are still waiting for ack on some events,
// we might have to wake up earlier to check if an app is anr'ing.
const nsecs_t nextAnrCheck = processAnrsLocked();
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
// We are about to enter an infinitely long sleep, because we have no commands or
// pending or queued events
if (nextWakeupTime == LONG_LONG_MAX) {
mDispatcherEnteredIdle.notify_all();
}
} // release lock
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);//进入epoll_wait
}
线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:
- callback:通过回调方法来唤醒;
- timeout:到达nextWakeupTime时间,超时唤醒;
- wake: 主动调用Looper的wake()方法;
4.3#dispatchOnceInnerLocked
<-InputDispatcher.cpp>
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();//当前时间,也是后面ANR计时的起点
if (!mDispatchEnabled) { //默认值为false
resetKeyRepeatLocked();//重置操作
}
if (mDispatchFrozen) { //默认值为false
return; //当分发被冻结,则不再处理超时和分发事件的工作,直接返回
}
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;//在enqueueInboundEventLocked()的过程中已设置mAppSwitchDueTime等于eventTime加上500ms
...
switch (mPendingEvent->type) {
...
case EventEntry::Type::KEY: {
std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEvent(*keyEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DropReason::NOT_DROPPED) {
dropReason = DropReason::APP_SWITCH;
}
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *keyEntry)) {
dropReason = DropReason::STALE;
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DropReason::BLOCKED;
}
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);// 分发按键事件
break;
}
...
}
...
if (done) {//分发操作完成,则进入该分支
if (dropReason != DropReason::NOT_DROPPED) {
dropInboundEventLocked(*mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
releasePendingEventLocked();//释放pending事件
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
该方法主要功能:
- 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(没有正在处理的事件);
4.4#dropInboundEventLocked
<-InputDispatcher.cpp>
void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) {
const char* reason;
switch (dropReason) {
case DropReason::POLICY:
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("Dropped event because policy consumed it.");
#endif
reason = "inbound event was dropped because the policy consumed it";
break;
case DropReason::DISABLED:
if (mLastDropReason != DropReason::DISABLED) {
ALOGI("Dropped event because input dispatch is disabled.");
}
reason = "inbound event was dropped because input dispatch is disabled";
break;
case DropReason::APP_SWITCH:
ALOGI("Dropped event because of pending overdue app switch.");
reason = "inbound event was dropped because of pending overdue app switch";
break;
case DropReason::BLOCKED:
ALOGI("Dropped event because the current application is not responding and the user "
"has started interacting with a different application.");
reason = "inbound event was dropped because the current application is not responding "
"and the user has started interacting with a different application";
break;
case DropReason::STALE:
ALOGI("Dropped event because it is stale.");
reason = "inbound event was dropped because it is stale";
break;
case DropReason::NO_POINTER_CAPTURE:
ALOGI("Dropped event because there is no window with Pointer Capture.");
reason = "inbound event was dropped because there is no window with Pointer Capture";
break;
case DropReason::NOT_DROPPED: {
LOG_ALWAYS_FATAL("Should not be dropping a NOT_DROPPED event");
return;
}
}
4.5#dispatchKeyLocked
<-InputDispatcher.cpp>
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
...
// Handle case where the policy asked us to try again later last time.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
if (currentTime < entry->interceptKeyWakeupTime) {// case1: 当前时间小于唤醒时间,则进入等待状态。
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) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {//case2: 让policy有机会执行拦截操作
std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
&InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
sp<IBinder> focusedWindowToken =
mFocusResolver.getFocusedWindowToken(getTargetDisplayId(*entry));
commandEntry->connectionToken = focusedWindowToken;
commandEntry->keyEntry = entry;
postCommandLocked(std::move(commandEntry));
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 == DropReason::NOT_DROPPED) {
*dropReason = DropReason::POLICY;
}
}
// Clean up if dropping the event.
if (*dropReason != DropReason::NOT_DROPPED) {//case3: 如果需要丢弃该事件,则执行清理操作
setInjectionResult(*entry,
*dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
: InputEventInjectionResult::FAILED);
mReporter->reportDroppedKey(entry->id);
return true;
}
// Identify targets.
std::vector<InputTarget> inputTargets;
InputEventInjectionResult injectionResult =
findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);//case4: 寻找焦点
if (injectionResult == InputEventInjectionResult::PENDING) {
return false;
}
setInjectionResult(*entry, injectionResult);
if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
return true;
}
// Add monitor channels from event's or focused display.
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
// Dispatch the key.
dispatchEventLocked(currentTime, entry, inputTargets);//只有injectionResult是成功,才有机会执行分发事件
return true;
}
在以下场景下,有可能无法分发事件:
- 当前时间小于唤醒时间(nextWakeupTime)的情况;
- policy需要提前拦截事件的情况;
- 需要drop事件的情况;
- 寻找聚焦窗口失败的情况;
如果成功跳过以上所有情况,则会进入执行事件分发的过程。
4.6#findFocusedWindowTargetsLocked
<-InputDispatcher.cpp>
InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked(
nsecs_t currentTime, const EventEntry& entry, std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime) {
std::string reason;
int32_t displayId = getTargetDisplayId(entry);
sp<InputWindowHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
...
if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {//找不到目标窗口,抛出ANR并开始计时
if (!mNoFocusedWindowTimeoutTime.has_value()) {
// We just discovered that there's no focused window. Start the ANR timer
std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout(
DEFAULT_INPUT_DISPATCHING_TIMEOUT);
mNoFocusedWindowTimeoutTime = currentTime + timeout.count();
mAwaitedFocusedApplication = focusedApplicationHandle;
mAwaitedApplicationDisplayId = displayId;
ALOGW("Waiting because no window has focus but %s may eventually add a "
"window when it finishes starting up. Will wait for %" PRId64 "ms",
mAwaitedFocusedApplication->getName().c_str(), millis(timeout));
*nextWakeupTime = *mNoFocusedWindowTimeoutTime;
return InputEventInjectionResult::PENDING;
} else if (currentTime > *mNoFocusedWindowTimeoutTime) {
// Already raised ANR. Drop the event
ALOGE("Dropping %s event because there is no focused window",
NamedEnum::string(entry.type).c_str());
return InputEventInjectionResult::FAILED;
} else {
// Still waiting for the focused window
return InputEventInjectionResult::PENDING;
}
}
// we have a valid, non-null focused window
resetNoFocusedWindowTimeoutLocked();
// Check permissions.
if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
return InputEventInjectionResult::PERMISSION_DENIED;
}
if (entry.type == EventEntry::Type::KEY) {
if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
*nextWakeupTime = *mKeyIsWaitingForEventsTimeout;
return InputEventInjectionResult::PENDING;
}
}
// Success! Output targets.
addWindowTargetLocked(focusedWindowHandle,//成功找到目标窗口,添加到目标窗口
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
BitSet32(0), inputTargets);
// Done.
return InputEventInjectionResult::SUCCEEDED;//成功找到目标窗口
}
寻找聚焦窗口失败的情况:
- 无窗口,无应用:Dropping event because there is no focused window or focused application.(这并不导致ANR的情况,因为没有机会调用handleTargetsNotReadyLocked)
- 无窗口, 有应用:Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.
4.7#dispatchEventLocked
<-InputDispatcher.cpp>
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
updateInteractionTokensLocked(*eventEntry, inputTargets);
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(*eventEntry);//向mCommandQueue队列添加doPokeUserActivityLockedInterruptible命令
for (const InputTarget& inputTarget : inputTargets) {
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);//找到目标连接
} else {
if (DEBUG_FOCUS) {
ALOGD("Dropping event delivery to target with channel '%s' because it "
"is no longer registered with the input dispatcher.",
inputTarget.inputChannel->getName().c_str());
}
}
}
}
该方法主要功能是将eventEntry发送到目标inputTargets. 其中pokeUserActivityLocked(eventEntry)方法最终会调用到Java层的PowerManagerService.java中的userActivityFromNative()方法. 这也是PMS中唯一的native call方法。
4.8#pokeUserActivityLocked
<-InputDispatcher.cpp>
void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {
...
std::unique_ptr<CommandEntry> commandEntry =
std::make_unique<CommandEntry>(&InputDispatcher::doPokeUserActivityLockedInterruptible);
commandEntry->eventTime = eventEntry.eventTime;
commandEntry->userActivityEventType = eventType;
commandEntry->displayId = displayId;
postCommandLocked(std::move(commandEntry));
}
void InputDispatcher::postCommandLocked(std::unique_ptr<CommandEntry> commandEntry) {
mCommandQueue.push_back(std::move(commandEntry));// 将命令加入mCommandQueue队尾
}
4.9#prepareDispatchCycleLocked
<-InputDispatcher.cpp>
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
...
if (connection->status != Connection::STATUS_NORMAL) {
return;//当连接已破坏,则直接返回
}
...
// Not splitting. Enqueue dispatch entries for the event as is.
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
4.10#enqueueDispatchEntriesLocked
<-InputDispatcher.cpp>
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
bool wasEmpty = connection->outboundQueue.empty();
// Enqueue dispatch entries for the requested modes.
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) {//当原先的outbound队列为空, 且当前outbound不为空的情况执行
startDispatchCycleLocked(currentTime, connection);
}
}
该方法主要功能:
- 根据dispatchMode来分别执行DispatchEntry事件加入队列的操作。
- 当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空情况下, 则执行startDispatchCycleLocked()方法.
4.11#enqueueDispatchEntryLocked
<-InputDispatcher.cpp>
void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget,
int32_t dispatchMode) {
...
int32_t inputTargetFlags = inputTarget.flags;
if (!(inputTargetFlags & dispatchMode)) {
return;//分发模式不匹配,则直接返回
}
inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
switch (newEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(newEntry);
dispatchEntry->resolvedEventId = keyEntry.id;
dispatchEntry->resolvedAction = keyEntry.action;
dispatchEntry->resolvedFlags = keyEntry.flags;
if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags)) {
return; // skip the inconsistent event
}
break;
}
...
}
...
// Enqueue the dispatch entry.
connection->outboundQueue.push_back(dispatchEntry.release());//添加到outboundQueue队尾
traceOutboundQueueLength(*connection);
}
该方法主要功能:
- 根据dispatchMode来决定是否需要加入outboundQueue队列;
- 根据EventEntry,来生成DispatchEntry事件;
- 将dispatchEntry加入到connection的outbound队列.
执行到这里,其实等于由做了一次搬运的工作,将InputDispatcher中mInboundQueue中的事件取出后, 找到目标window后,封装dispatchEntry加入到connection的outbound队列.
4.12#startDispatchCycleLocked
<-InputDispatcher.cpp>
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
...
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {//当Connection状态正常,且outboundQueue不为空
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const std::chrono::nanoseconds timeout =
getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
dispatchEntry->timeoutTime = currentTime + timeout.count();//设置deliveryTime时间
// Publish the event.
status_t status;
const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
switch (eventEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
std::array<uint8_t, 32> hmac = getSignature(keyEntry, *dispatchEntry);
// Publish the key event.
status = connection->inputPublisher//发布Key事件
.publishKeyEvent(dispatchEntry->seq,
dispatchEntry->resolvedEventId, keyEntry.deviceId,
keyEntry.source, keyEntry.displayId,
std::move(hmac), dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags, keyEntry.keyCode,
keyEntry.scanCode, keyEntry.metaState,
keyEntry.repeatCount, keyEntry.downTime,
keyEntry.eventTime);
break;
}
...
}
// Check the result.
if (status) {//publishKeyEvent失败情况
if (status == WOULD_BLOCK) {
if (connection->waitQueue.empty()) {//pipe已满,但waitQueue为空. 不正常的行为
ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
"This is unexpected because the wait queue is empty, so the pipe "
"should be empty and we shouldn't have any problems writing an "
"event to it, status=%s(%d)",
connection->getInputChannelName().c_str(), statusToString(status).c_str(),
status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
} else {
// Pipe is full and we are waiting for the app to finish process some events
// before sending more events to it.
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
"waiting for the application to catch up",
connection->getInputChannelName().c_str());// 处于阻塞状态
#endif
}
} else {
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);//不不正常的行为
}
return;
}
// Re-enqueue the event on the wait queue.
//从outboundQueue中取出事件,重新放入waitQueue队列
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
traceOutboundQueueLength(*connection);
connection->waitQueue.push_back(dispatchEntry);
if (connection->responsive) {
mAnrTracker.insert(dispatchEntry->timeoutTime,
connection->inputChannel->getConnectionToken());
}
traceWaitQueueLength(*connection);
}
}
startDispatchCycleLocked的主要功能: 从outboundQueue中取出事件,重新放入waitQueue队列
- startDispatchCycleLocked触发时机:当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空。
- startDispatchCycleLocked主要功能: 从outboundQueue中取出事件,重新放入waitQueue队列
- publishKeyEvent执行结果status不等于OK的情况下:
- WOULD_BLOCK,且waitQueue等于空,则调用abortBrokenDispatchCycleLocked(),该方法最终会调用到Java层的IMS.notifyInputChannelBroken().
- WOULD_BLOCK,且waitQueue不等于空,则处于阻塞状态,即inputPublisherBlocked=true
其他情况,则调用abortBrokenDispatchCycleLocked
- abortBrokenDispatchCycleLocked()方法最终会调用到Java层的IMS.notifyInputChannelBroken().
4.13#publishKeyEvent
<-InputTransport.cpp>
status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action,
int32_t flags, int32_t keyCode, int32_t scanCode,
int32_t metaState, int32_t repeatCount, nsecs_t downTime,
nsecs_t eventTime) {
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
msg.header.seq = seq;
msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.displayId = displayId;
msg.body.key.hmac = std::move(hmac);
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;
return mChannel->sendMessage(&msg);
}
InputChannel通过socket向远端的socket发送消息。
4.14#releasePendingEventLocked
<-InputDispatcher.cpp>
void InputDispatcher::releasePendingEventLocked() {
if (mPendingEvent) {
releaseInboundEventLocked(mPendingEvent);//释放mPendingEvent对象,并记录到mRecentQueue队列
mPendingEvent = nullptr;//置空mPendingEvent变量.
}
}
4.15#runCommandsLockedInterruptible
<-InputDispatcher.cpp>
bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.empty()) {
return false;
}
do {
std::unique_ptr<CommandEntry> commandEntry = std::move(mCommandQueue.front());//从mCommandQueue队列的头部取出第一个元素
mCommandQueue.pop_front();
Command command = commandEntry->command;
command(*this, commandEntry.get()); // commands are implicitly 'LockedInterruptible'
commandEntry->connection.clear();
} while (!mCommandQueue.empty());
return true;
}
通过循环方式处理完mCommandQueue队列的所有命令,处理过程从mCommandQueue中取出CommandEntry. runCommandsLockedInterruptible是不断地从mCommandQueue队列取出命令,然后执行直到全部执行完成。 除了doPokeUserActivityLockedInterruptible,还有其他如下命令:
- doNotifyANRLockedInterruptible
- doInterceptKeyBeforeDispatchingLockedInterruptible
- doDispatchCycleFinishedLockedInterruptible
- doNotifyInputChannelBrokenLockedInterruptible
- doNotifyConfigurationChangedInterruptible
4.16#doPokeUserActivityLockedInterruptible
<-InputDispatcher.cpp>
void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
mLock.unlock();
mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType,
commandEntry->displayId);
mLock.lock();
}
4.17#pokeUserActivity
<-com_android_server_input_InputManagerService.cpp>
void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) {
ATRACE_CALL();
android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
}
4.18#android_server_PowerManagerService_userActivity
<-com_android_server_power_PowerManagerService.cpp>
void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
int32_t displayId) {
if (gPowerManagerServiceObj) {
...
env->CallVoidMethod(gPowerManagerServiceObj,
gPowerManagerServiceClassInfo.userActivityFromNative,
nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
checkAndClearExceptionFromCallback(env, "userActivityFromNative");
}
}
4.19#PMS.userActivityFromNative
<-PowerManagerService.java>
private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID);
}
private void userActivityInternal(int displayId, long eventTime, int event, int flags,
int uid) {
synchronized (mLock) {
if (displayId == Display.INVALID_DISPLAY) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
updatePowerStateLocked();
}
return;
}
final DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
if (displayInfo == null) {
return;
}
final int groupId = displayInfo.displayGroupId;
if (groupId == Display.INVALID_DISPLAY_GROUP) {
return;
}
if (userActivityNoUpdateLocked(groupId, eventTime, event, flags, uid)) {
updatePowerStateLocked();
}
}
}
4.20 小结
- dispatchOnceInnerLocked(): 从InputDispatcher的mInboundQueue队列,取出事件EventEntry。另外该方法开始执行的时间点(currentTime)便是后续事件dispatchEntry的分发时间(deliveryTime)
- dispatchKeyLocked():满足一定条件时会添加命令doInterceptKeyBeforeDispatchingLockedInterruptible;
- enqueueDispatchEntryLocked():生成事件DispatchEntry并加入connection的outbound队列
- startDispatchCycleLocked():从outboundQueue中取出事件DispatchEntry, 重新放入connection的waitQueue队列;
- InputChannel.sendMessage通过socket方式将消息发送给远程进程;
- runCommandsLockedInterruptible():通过循环遍历地方式,依次处理mCommandQueue队列中的所有命令。而mCommandQueue队列中的命令是通过postCommandLocked()方式向该队列添加的。
5. Input系统—UI线程
Activity的生命周期的回调方法都是运行在主线程,也称之为UI线程,所有UI相关的操作都需要运行在该线程。所以这里从Activity最基本的创建过程开始说起。
frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/view/WindowManagerGlobal.java
frameworks/base/core/java/android/view/ViewRootImpl.java
frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/wm/Session.java
frameworks/base/services/core/java/com/android/server/wm/WindowState.java
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/libs/input/InputTransport.cpp
frameworks/base/core/java/android/view/InputEventReceiver.java
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
#xxxActivity.java
├──onCreate(Bundle savedInstanceState)
#WindowManagerGlobal
├──addView()
└──root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl对象
| #ViewRootImpl.java
| ├──ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,boolean useSfChoreographer)
| └──mWindowSession = session;//WindowManagerGlobal.getWindowSession()
| #WindowManagerGlobal
| ├──getWindowSession()
| └──InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();//获取IMS的代理类
| | #InputMethodManager.java
| | ├──ensureDefaultInstanceForDefaultDisplayIfNecessary()
| | └──forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
| | └──InputMethodManager instance = sInstanceMap.get(displayId);//根据displayId获取IMS代理对象
| └──IWindowManager windowManager = getWindowManagerService();//获取WMS的代理类
| └──windowManager.openSession(new IWindowSessionCallback.Stub() //经过Binder调用,最终调用WMS
| #WindowManagerService.java
| ├──openSession(IWindowSessionCallback callback)
| └──return new Session(this, callback);
└──root.setView(view, wparams, panelParentView, userId);
#ViewRootImpl.java
├──setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId)
└──inputChannel = new InputChannel();//创建InputChannel对象
└──res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets, mTempControls);//通过Binder调用,进入system进程的Session
| #Session.java
| ├──addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls)
| └──return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
| #WindowManagerService.java
| ├──addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsState requestedVisibility,nputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls)
| └──final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);
| | #WindowState.java
| | ├──WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,PowerManagerWrapper powerManagerWrapper)
| | └── mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(mActivityRecord != null? mActivityRecord.getInputApplicationHandle(false /* update */) : null,getDisplayId()));
| └──win.openInputChannel(outInputChannel);
| | #WindowState.java
| | ├──openInputChannel(InputChannel outInputChannel)
| | └──mInputChannel = mWmService.mInputManager.createInputChannel(name);
| | #InputManagerService.java
| | ├──createInputChannel(String name)
| | └──return nativeCreateInputChannel(mPtr, name);
| | #com_android_server_input_InputManagerService.cpp
| | ├──nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,jstring nameObj)
| | └──createInputChannel(JNIEnv* /* env */, const std::string& name)
| | └──return mInputManager->getDispatcher()->createInputChannel(name);
| | #InputDispatcher.cpp
| | ├──createInputChannel(const std::string& name)
| | └──status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);//创建一对socket
| | | #InputTransport.cpp
| | | ├──openInputChannelPair(const std::string& name,std::unique_ptr<InputChannel>& outServerChannel,std::unique_ptr<InputChannel>& outClientChannel)
| | | └──socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)//创建socket对
| | | └──outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);//创建server InputChannel对象
| | | └──outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);//创建client InputChannel对象
| | └──mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);//将该fd添加到Looper监听
| | └──mLooper->wake();//connection改变, 则唤醒looper
| └──focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, false /*updateInputWindows*/);//新添加window能接收按下操作,则更新聚焦窗口
| └──displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);//设置当前聚焦窗口
| #InputMonitor.java
| ├──updateInputWindowsLw(boolean force)
| └──scheduleUpdateInputWindows()
| └──mHandler.post(mUpdateInputWindows);
└──mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());//创建WindowInputEventReceiver对象
#ViewRootImpl.java
├──InputEventReceiver(InputChannel inputChannel, Looper looper)
└──mMessageQueue = looper.getQueue();//UI线程消息队列
└──mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),inputChannel, mMessageQueue);
#android_view_InputEventReceiver.cpp
├──nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,jobject inputChannelObj, jobject messageQueueObj)
└──sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,receiverWeak, inputChannel, messageQueue);//创建NativeInputEventReceiver对象
└──status_t status = receiver->initialize();
#android_view_InputEventReceiver.cpp
├──initialize()
└──setFdEvents(int events)
└──int fd = mInputConsumer.getChannel()->getFd();
└──if(events)
| └──mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);//将socket客户端的fd添加到主线程的消息池
└──else
└──mMessageQueue->getLooper()->removeFd(fd);
5.1#onCreate
<-xxxActivity.java>
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account_bind);
...
}
Activity启动是由system进程控制:
- handleLaunchActivity():会调用Activity.onCreate(), 该方法内再调用setContentView(),经过AMS与WMS的各种交互,层层调用后,进入handleResumeActivity()
- handleResumeActivity():会调用Activity.makeVisible(),该方法继续调用便会执行到WindowManagerImpl.addView(), 该方法内部再调用WindowManagerGlobal.addView()
5.2#addView
<-WindowManagerGlobal.java>
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl对象
...
root.setView(view, wparams, panelParentView, userId);
...
}
5.3#ViewRootImpl
<-ViewRootImpl.java>
public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
boolean useSfChoreographer) {
...
mWindowSession = session;//WindowManagerGlobal.getWindowSession()
mDisplay = display;
mThread = Thread.currentThread();//主线程
mWindow = new W(this);
...
mChoreographer = useSfChoreographer? Choreographer.getSfInstance() : Choreographer.getInstance();//界面刷新软中断
...
}
5.3.1#getWindowSession
<-WindowManagerGlobal.java>
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();//获取IMS的代理类
IWindowManager windowManager = getWindowManagerService();//获取WMS的代理类
sWindowSession = windowManager.openSession(//经过Binder调用,最终调用WMS
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
});
}catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
5.3.2#ensureDefaultInstanceForDefaultDisplayIfNecessary
<-InputMethodManager.java>
public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
}
private static InputMethodManager forContextInternal(int displayId, Looper looper) {
final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
synchronized (sLock) {
InputMethodManager instance = sInstanceMap.get(displayId);//根据displayId获取IMS代理对象
if (instance != null) {
return instance;
}
instance = createInstance(displayId, looper);
// For backward compatibility, store the instance also to sInstance for default display.
if (sInstance == null && isDefaultDisplay) {
sInstance = instance;
}
sInstanceMap.put(displayId, instance);
return instance;
}
}
5.3.3#WMS.openSession
<-WindowManagerService.java>
public IWindowSession openSession(IWindowSessionCallback callback) {
return new Session(this, callback);
}
再次经过Binder将数据写回app进程,则获取的便是Session的代理对象。
5.3.4#setView
<-ViewRootImpl.java>
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
synchronized (this) {
...
requestLayout();
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
inputChannel = new InputChannel();//创建InputChannel对象
}
...
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,//通过Binder调用,进入system进程的Session
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
mTempControls);
...
if (inputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());//创建WindowInputEventReceiver对象
if (ENABLE_INPUT_LATENCY_TRACKING && mAttachInfo.mThreadedRenderer != null) {
InputMetricsListener listener = new InputMetricsListener();
mHardwareRendererObserver = new HardwareRendererObserver(
listener, listener.data, mHandler, true /*waitForPresentTime*/);
mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
}
}
...
}
该方法主要功能:
- 创建Java层的InputChannel对象mInputChannel
- 向WMS注册InputChannel信息,通过InputChannel.openInputChannelPair创建的socket pair,将其中的客户端赋值给mInputChannel.
- 创建WindowInputEventReceiver对象
跨进程调用,进入binder thread执行如下方法:
5.4#Session.addToDisplayAsUser
<-Session.java>
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
}
5.4.1#WMS.addWindow
<-WindowManagerService.java>
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
int displayId, int requestUserId, InsetsState requestedVisibility,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls) {
...
synchronized (mGlobalLock) {
...
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], attrs, viewVisibility, session.mUid, userId,
session.mCanAddInternalSystemWindow);
...
displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
...
boolean focusChanged = false;
if (win.canReceiveKeys()) {
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);//新添加window能接收按下操作,则更新聚焦窗口
if (focusChanged) {
imMayMove = false;
}
}
...
if (focusChanged) {
displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
false /*updateInputWindows*/);
}
displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);//设置当前聚焦窗口
...
}
...
}
5.4.2#WindowState
<-WindowState.java>
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
PowerManagerWrapper powerManagerWrapper) {
...
mToken = token;
...
mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(
mActivityRecord != null
? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
getDisplayId()));
mInputWindowHandle.setOwnerPid(s.mPid);
mInputWindowHandle.setOwnerUid(s.mUid);
mInputWindowHandle.setName(getName());
mInputWindowHandle.setPackageName(mAttrs.packageName);
mInputWindowHandle.setLayoutParamsType(mAttrs.type);
...
}
5.4.3#updateFocusedWindowLocked
<-RootWindowContainer.java>
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
mTopFocusedAppByProcess.clear();
...
if (mTopFocusedDisplayId != topFocusedDisplayId) {
mTopFocusedDisplayId = topFocusedDisplayId;
mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId);
}
return changed;
}
5.4.4#updateInputWindowsLw
<-InputMonitor.java>
void updateInputWindowsLw(boolean force) {
if (!force && !mUpdateInputWindowsNeeded) {
return;
}
scheduleUpdateInputWindows();
}
private void scheduleUpdateInputWindows() {
if (mDisplayRemoved) {
return;
}
if (!mUpdateInputWindowsPending) {
mUpdateInputWindowsPending = true;
mHandler.post(mUpdateInputWindows);
}
}
5.5#openInputChannel
<-WindowState.java>
void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
String name = getName();
mInputChannel = mWmService.mInputManager.createInputChannel(name);
mInputChannelToken = mInputChannel.getToken();
mInputWindowHandle.setToken(mInputChannelToken);
mWmService.mInputToWindowMap.put(mInputChannelToken, this);
if (outInputChannel != null) {
mInputChannel.copyTo(outInputChannel);
} else {
// If the window died visible, we setup a fake input channel, so that taps
// can still detected by input monitor channel, and we can relaunch the app.
// Create fake event receiver that simply reports all events as handled.
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);
}
}
5.5.1#createInputChannel
<-InputManagerService.java>
public InputChannel createInputChannel(String name) {
return nativeCreateInputChannel(mPtr, name);
}
private static native InputChannel nativeCreateInputChannel(long ptr, String name);
5.5.2#nativeCreateInputChannel
<-com_android_server_input_InputManagerService.cpp>
static jobject nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,
jstring nameObj) {
...
base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
...
}
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
JNIEnv* /* env */, const std::string& name) {
ATRACE_CALL();
return mInputManager->getDispatcher()->createInputChannel(name);
}
5.5.3#createInputChannel
<-InputDispatcher.cpp>
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
...
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);//创建一对socket
if (result) {
return base::Error(result) << "Failed to open input channel pair with name " << name;
}
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
int fd = serverChannel->getFd();
sp<Connection> connection =
new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);//创建Connection
if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
ALOGE("Created a new connection, but the token %p is already known", token.get());
}
mConnectionsByToken.emplace(token, connection);
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);//将该fd添加到Looper监听
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();//connection改变, 则唤醒looper
return clientChannel;
}
static status_t openInputChannelPair(const std::string& name,
std::shared_ptr<InputChannel>& serverChannel,
std::unique_ptr<InputChannel>& clientChannel) {
std::unique_ptr<InputChannel> uniqueServerChannel;
status_t result = InputChannel::openInputChannelPair(name, uniqueServerChannel, clientChannel);
serverChannel = std::move(uniqueServerChannel);
return result;
}
5.5.4#openInputChannelPair
<-InputTransport.cpp>
status_t InputChannel::openInputChannelPair(const std::string& name,
std::unique_ptr<InputChannel>& outServerChannel,
std::unique_ptr<InputChannel>& outClientChannel) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {//真正创建socket对的地方
status_t result = -errno;
ALOGE("channel '%s' ~ Could not create socket pair. errno=%s(%d)", name.c_str(),
strerror(errno), errno);
outServerChannel.reset();
outClientChannel.reset();
return result;
}
int bufferSize = SOCKET_BUFFER_SIZE;//32k
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
sp<IBinder> token = new BBinder();
std::string serverChannelName = name + " (server)";
android::base::unique_fd serverFd(sockets[0]);
outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);//创建server InputChannel对象
std::string clientChannelName = name + " (client)";
android::base::unique_fd clientFd(sockets[1]);
outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);//创建client InputChannel对象
return OK;
}
该方法主要功能:
- 创建socket pair; (非阻塞式的socket)
- 设置两个socket的接收和发送的buffer上限为32KB;
- 创建client和server的Native层InputChannel对象;
- sockets[0]所对应的InputChannel名称的后缀为(server);
- sockets[1]所对应的InputChannel名称的后缀为(client)
5.6#WindowInputEventReceiver
<-ViewRootImpl.java>
final class WindowInputEventReceiver extends InputEventReceiver {
//inputChannel是指socket客户端,Looper是指UI线程的Looper
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper); //【见小节3.2】
}
...
}
5.6.1#InputEventReceiver
<-InputEventReceiver.java>
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
...
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();//UI线程消息队列
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
private static native long nativeInit(WeakReference<InputEventReceiver> receiver,
InputChannel inputChannel, MessageQueue messageQueue);
5.6.2#nativeInit
<-android_view_InputEventReceiver.cpp>
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
std::shared_ptr<InputChannel> inputChannel =
android_view_InputChannel_getInputChannel(env, inputChannelObj);
...
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);//获取UI主线程的消息队列
...
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);//创建NativeInputEventReceiver对象
status_t status = receiver->initialize();
...
receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
5.6.3#NativeInputEventReceiver
<-android_view_InputEventReceiver.cpp>
NativeInputEventReceiver::NativeInputEventReceiver(
JNIEnv* env, jobject receiverWeak, const std::shared_ptr<InputChannel>& inputChannel,
const sp<MessageQueue>& messageQueue)
: mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mInputConsumer(inputChannel),//inputChannel是socket客户端
mMessageQueue(messageQueue),
mBatchedInputEventPending(false),
mFdEvents(0) {
}
5.6.4#initialize
<-android_view_InputEventReceiver.cpp>
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);//将socket客户端的fd添加到主线程的消息池
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
5.7小结
ViewRootImpl的setView()过程:
- 创建socket pair,作为InputChannel:
- socket服务端保存到system_server中的WindowState的mInputChannel;
- socket客户端通过binder传回到远程进程的UI主线程ViewRootImpl的mInputChannel;
- 紧接着,完成了两个线程的epoll监听工作:
- IMS.createInputChannel(): “InputDispatcher”线程监听socket服务端,收到消息后回调InputDispatcher.handleReceiveCallback();
- setFdEvents(): UI主线程监听socket客户端,收到消息后回调NativeInputEventReceiver.handleEvent().
|