Android 12 Input系统理解

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", devic
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值