Android13 手势监听实现

packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java

private void updateIsEnabled() {
        boolean isEnabled = mIsAttached && mIsGesturalModeEnabled;
        if (isEnabled == mIsEnabled) {
            return;
        }
        mIsEnabled = isEnabled;
        disposeInputChannel();

        if (mEdgeBackPlugin != null) {
            mEdgeBackPlugin.onDestroy();
            mEdgeBackPlugin = null;
        }

        if (!mIsEnabled) {
            mGestureNavigationSettingsObserver.unregister();
            if (DEBUG_MISSING_GESTURE) {
                Log.d(DEBUG_MISSING_GESTURE_TAG, "Unregister display listener");
            }
            mPluginManager.removePluginListener(this);
      TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
            DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
            mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(null));

            try {
                mWindowManagerService.unregisterSystemGestureExclusionListener(
                        mGestureExclusionListener, mDisplayId);
            } catch (RemoteException | IllegalArgumentException e) {
                Log.e(TAG, "Failed to unregister window manager callbacks", e);
            }

        } else {
            mGestureNavigationSettingsObserver.register();
            updateDisplaySize();
            if (DEBUG_MISSING_GESTURE) {
                Log.d(DEBUG_MISSING_GESTURE_TAG, "Register display listener");
            }
            TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
                    mMainExecutor::execute, mOnPropertiesChangedListener);
            mPipOptional.ifPresent(
                    pip -> pip.setOnIsInPipStateChangedListener(mOnIsInPipStateChangedListener));

            try {
                mWindowManagerService.registerSystemGestureExclusionListener(
                        mGestureExclusionListener, mDisplayId);
            } catch (RemoteException | IllegalArgumentException e) {
                Log.e(TAG, "Failed to register window manager callbacks", e);
            }

            // Register input event receiver
            // 新建一个mInputMonitor 通过 monitorGestureInput
            mInputMonitor = InputManager.getInstance().monitorGestureInput(
                    "edge-swipe", mDisplayId);
            // 封装成 InputEventReceiver 对于收到的事件将在 InputEventReceiver 里面实现
            mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
                    mInputMonitor.getInputChannel(), Looper.getMainLooper(),
                    Choreographer.getInstance(), this::onInputEvent);

            // Add a nav bar panel window
            mIsNewBackAffordanceEnabled = mFeatureFlags.isEnabled(Flags.NEW_BACK_AFFORDANCE);
            resetEdgeBackPlugin();
            mPluginManager.addPluginListener(
                    this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
        }
        // Update the ML model resources.
        updateMLModelState();
    }
services/core/java/com/android/server/input/InputManagerService.java


public InputMonitor monitorGestureInput(IBinder monitorToken, @NonNull String requestedName,
            int displayId) {
        if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,
                "monitorGestureInput()")) {
            throw new SecurityException("Requires MONITOR_INPUT permission");
        }
        Objects.requireNonNull(requestedName, "name must not be null.");
        Objects.requireNonNull(monitorToken, "token must not be null.");

        if (displayId < Display.DEFAULT_DISPLAY) {
            throw new IllegalArgumentException("displayId must >= 0.");
        }
        // 命名为 Gesture Monitor ***
        final String name = "[Gesture Monitor] " + requestedName;
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();

        final long ident = Binder.clearCallingIdentity();
        try {
        	// 通过 createSpyWindowGestureMonitor创建 InputChannel
            final InputChannel inputChannel =
                            createSpyWindowGestureMonitor(monitorToken, name, displayId, pid, uid);
            // 构造 InputMonitor
            return new InputMonitor(inputChannel, new InputMonitorHost(inputChannel.getToken()));
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
services/core/java/com/android/server/input/InputManagerService.java

private InputChannel createSpyWindowGestureMonitor(IBinder monitorToken, String name,
            int displayId, int pid, int uid) {
        // 新建sc  在sf建立一个对应的surfac
        final SurfaceControl sc = mWindowManagerCallbacks.createSurfaceForGestureMonitor(name,
                displayId);
        if (sc == null) {
            throw new IllegalArgumentException(
                    "Could not create gesture monitor surface on display: " + displayId);
        }
        // 新建一个InputChannel
        final InputChannel channel = createInputChannel(name);

        try {
            monitorToken.linkToDeath(() -> removeSpyWindowGestureMonitor(channel.getToken()), 0);
        } catch (RemoteException e) {
            Slog.i(TAG, "Client died before '" + name + "' could be created.");
            return null;
        }
        synchronized (mInputMonitors) {
            mInputMonitors.put(channel.getToken(),
            		// 新建一个 GestureMonitorSpyWindow 重要
                    new GestureMonitorSpyWindow(monitorToken, name, displayId, pid, uid, sc,
                            channel));
        }

        final InputChannel outInputChannel = new InputChannel();
        channel.copyTo(outInputChannel);
        return outInputChannel;
    }

services/core/java/com/android/server/input/GestureMonitorSpyWindow.java

GestureMonitorSpyWindow(IBinder token, String name, int displayId, int pid, int uid,
            SurfaceControl sc, InputChannel inputChannel) {
        mMonitorToken = token;
        mClientChannel = inputChannel;
        mInputSurface = sc;
		
		// 居然还专门构造了一个  ApplicationHandle
        mApplicationHandle = new InputApplicationHandle(null, name,
                DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
        // 新建 WindowHandle
        mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);

        mWindowHandle.name = name;
        mWindowHandle.token = mClientChannel.getToken();
        // 添加一些窗口标记
        mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
        mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
        mWindowHandle.ownerPid = pid;
        mWindowHandle.ownerUid = uid;
        mWindowHandle.scaleFactor = 1.0f;
        mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);
        // 重要的inputConfig 最重要的是 InputConfig.SPY  后面分析
        mWindowHandle.inputConfig =
                InputConfig.NOT_FOCUSABLE | InputConfig.SPY | InputConfig.TRUSTED_OVERLAY;
		
		// 把sc的信息,连同mWindowHandle 信息传给 sf, 后续该信息将会同步到 inputflinger
        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
        // 注意 设置层级 为最高  
        t.setLayer(mInputSurface, Integer.MAX_VALUE);
        t.setPosition(mInputSurface, 0, 0);
        t.setCrop(mInputSurface, null /* crop to parent surface */);
        t.show(mInputSurface);

        t.apply();
    }


接下来到 InputDispatcher.cpp

dispatcher/InputDispatcher.cpp

InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
        nsecs_t currentTime, const MotionEntry& entry, std::vector<InputTarget>& inputTargets,
        nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) {
    ATRACE_CALL();

   
        // 去寻找对应的窗口, 能找到的话 ,就只能找到一个  找的是非Spy类型的窗口
        newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState,
                                                           isStylus, isDown /*addOutsideTargets*/);

      	........
		
		// 找的是 Spy 类型的窗口 ,就是 之前添加的estureMonitorSpyWindow
        std::vector<sp<WindowInfoHandle>> newTouchedWindows =
                findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus);
        .......
    return injectionResult;
}

std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
        int32_t displayId, int32_t x, int32_t y, bool isStylus) const {
    // Traverse windows from front to back and gather the touched spy windows.
    std::vector<sp<WindowInfoHandle>> spyWindows;
    const auto& windowHandles = getWindowHandlesLocked(displayId);
    for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
        const WindowInfo& info = *windowHandle->getInfo();

        if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus)) {
            continue;
        }
        if (!info.isSpy()) {
            // The first touched non-spy window was found, so return the spy windows touched so far.
            return spyWindows;
        }
        // 从上到下,遍历所有windowHandle,找出所有Spy类型的windowHandle,并返回
        spyWindows.push_back(windowHandle);
    }
    return spyWindows;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值