MapleStory

Touch Event Dispatch Procedure in Android 10

触摸事件只会分发给可见的能够接受事件的窗口

在P版本上相关的成员
ViewRootImpl
WindowManagerService
InputDispatcher

Q版本相关的成员
ViewRootImpl
WindowManagerService
SurfaceFlinger
InputDispatcher

  1. 当前窗口在执行完onResume后由框架向WindowManagerService添加窗口,并开始接收Input事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ActivityThread.java
    wm.addView(decor, l);
    ViewRootImpl.java
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
    getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
    mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
    mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
    mTempInsets);
    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
    Looper.myLooper());
  2. WindowManagerService添加窗口
    打开InputChannel
    更新焦点窗口
    更新Input窗口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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*/);
    if (focusChanged) {
    imMayMove = false;
    }
    }
    if (focusChanged) {
    displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
    false /*updateInputWindows*/);
    }
    displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
  3. 焦点窗口被设置到SurfaceFlinger

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    // DisplayContent.java
    int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
    // InputMonitor.java
    void updateInputWindowsLw(boolean force) {
    if (!force && !mUpdateInputWindowsNeeded) {
    return;
    }
    scheduleUpdateInputWindows();
    }
    mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
    // 不更新的场景
    if (inputChannel == null || inputWindowHandle == null || w.mRemoved
    || w.cantReceiveTouchInput()) {
    if (w.mWinAnimator.hasSurface()) {
    mInputTransaction.setInputWindowInfo(
    w.mWinAnimator.mSurfaceController.mSurfaceControl, mInvalidInputWindow);
    }
    // Skip this window because it cannot possibly receive input.
    return;
    }
    // 更新的场景
    populateInputWindowHandle(
    inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
    if (w.mWinAnimator.hasSurface()) {
    mInputTransaction.setInputWindowInfo(
    w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
    }
    // android_view_SurfaceControl.cpp
    static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactionObj,
    jlong nativeObject, jobject inputWindow) {
    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
    sp<NativeInputWindowHandle> handle = android_view_InputWindowHandle_getHandle(
    env, inputWindow);
    handle->updateInfo();
    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    transaction->setInputWindowInfo(ctrl, *handle->getInfo());
    }
  4. SurfaceFlinger设置可以接收事件的窗口到InputDispatcher

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    void SurfaceFlinger::updateInputWindowInfo() {
    std::vector<InputWindowInfo> inputHandles;
    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
    if (layer->hasInput()) {
    // When calculating the screen bounds we ignore the transparent region since it may
    // result in an unwanted offset.
    inputHandles.push_back(layer->fillInputInfo());
    }
    });
    mInputFlinger->setInputWindows(inputHandles,
    mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
    : nullptr);
    }
  5. InputDispatcher根据InputWIndowHandle的属性更新分发窗口


Comments