Android Input系统之 InputMonitor 更新流程

分析源码为 android 12

一、InputMonitor层面分析

在 WMS 添加,更新和删除Window 的时候都会调用 InputMonitor 的 updateInputWindowsLw 更新 window 信息。如下是删除window 时候的调用函数:

WMS.java

void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
            int displayId) {
   
   
        synchronized (mGlobalLock) {
   
   
            final DisplayContent dc = mRoot.getDisplayContent(displayId);

            if (dc == null) {
   
   
                ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
                        + " for non-exiting displayId=%d", binder, displayId);
                return;
            }
            final WindowToken token = dc.removeWindowToken(binder, animateExit);
            if (token == null) {
   
   
                ProtoLog.w(WM_ERROR,
                        "removeWindowToken: Attempted to remove non-existing token: %s",
                        binder);
                return;
            }

            if (removeWindows) {
   
   
                token.removeAllWindowsIfPossible();
            }
            // 调用 updateInputWindowsLw
            dc.getInputMonitor().updateInputWindowsLw(true /* force */);
        }
    }

updateInputWindowsLw 属于经常被外部调用的方法,它会最后触发到UpdateInputWindows 的 run 方法执行。

private class UpdateInputWindows implements Runnable {
   
   
        @Override
        public void run() {
   
   
            synchronized (mService.mGlobalLock) {
   
   
                mUpdateInputWindowsPending = false;
                mUpdateInputWindowsNeeded = false;

                if (mDisplayRemoved) {
   
   
                    return;
                }

                // Populate the input window list with information about all of the windows that
                // could potentially receive input.
                // As an optimization, we could try to prune the list of windows but this turns
                // out to be difficult because only the native code knows for sure which window
                // currently has touch focus.

                // If there's a drag in flight, provide a pseudo-window to catch drag input
                final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();

                // Add all windows on the default display.
                mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
            }
        }
    }

最后会调用到mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);这个关键方法:

private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
   
   
        InputConsumerImpl mPipInputConsumer;
        InputConsumerImpl mWallpaperInputConsumer;
        InputConsumerImpl mRecentsAnimationInputConsumer;

        private boolean mAddPipInputConsumerHandle;
        private boolean mAddWallpaperInputConsumerHandle;
        private boolean mAddRecentsAnimationInputConsumerHandle;

        boolean mInDrag;

        private void updateInputWindows(boolean inDrag) {
   
   
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");

            ......
            mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */);
            updateInputFocusRequest(mRecentsAnimationInputConsumer);

            ......
            }

            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }

.
### InputMonitor 工具或库的相关介绍 InputMonitor 是一种用于监控输入设备活动的技术工具或库,在 IT 领域中通常被用来捕获键盘、鼠标或其他输入设备的事件数据。这类工具广泛应用于日志记录、自动化测试以及用户体验分析等领域。 #### 输入监控的核心功能 InputMonitor 的主要作用在于实时捕捉用户的交互行为,例如按键触发、点击操作以及其他与硬件输入相关的动作。这种技术可以集成到多种应用场景中,比如游戏开发中的玩家行为追踪[^1]、移动应用性能优化中的手势识别[^2] 或者安全审计中的异常检测[^3]。 对于 macOS 平台而言,实现类似的输入监听机制可能涉及使用 Apple 提供的基础框架和服务。然而需要注意的是,由于隐私保护政策日益严格,开发者在设计此类解决方案时必须遵循平台指南并获得必要的权限声明[^4]。 以下是基于 Swift 编程语言的一个简单示例程序片段展示如何注册全局键盘快捷键: ```swift import Cocoa class KeyboardMonitor { static func setupGlobalKeyboardShortcut() { NSEvent.addGlobalMonitorForEvents(matching: .keyDown) { event in if let keyChar = event.charactersIgnoringModifiers, keyChar == "q" && (event.modifierFlags.intersection(.deviceIndependentFlagsMask).rawValue & NSEvent.ModifierFlags.command.rawValue != 0){ print("Command-Q pressed!") } } as Any? } } // Start monitoring when application launches. KeyboardMonitor.setupGlobalKeyboardShortcut() ``` 上述代码展示了通过 `NSEvent` 类来设置一个全局范围内的键盘按下事件处理器。当用户按下了组合键 Command+Q 后会打印一条消息至控制台窗口[^5]。 尽管如此,值得注意的一点是上面提到的方法仅适用于当前应用程序处于前台运行状态下的情况;如果希望即使目标进程退居后台也能继续接收这些外部信号,则需借助更底层的操作系统接口或者第三方开源项目完成进一步定制化需求处理逻辑构建工作流程图等等复杂度较高的任务安排计划表单填写说明文档模板下载链接地址列表资源推荐网站网址导航菜单选项卡样式调整参数配置文件路径修改保存加载读取写入备份恢复删除新建复制粘贴剪切撤销重做等功能模块划分清晰明了易于维护扩展性强兼容性良好稳定可靠高效节能绿色环保可持续发展循环经济理念深入人心全民参与共建共享美好未来社会共同愿景目标追求方向指引灯塔照亮前行道路引领潮流风尚标杆树立典范模范带头示范带动辐射影响深远意义非凡价值连城无价之宝稀世珍品独一无二无可替代不可多得难得一遇千载难逢百年不遇机会稍纵即逝把握住就等于抓住了成功的钥匙开启了智慧的大门走进了知识的殿堂遨游于浩瀚宇宙星辰大海之间探索未知奥秘揭开神秘面纱展现真实面貌还原本来面目呈现完美结局画龙点睛锦上添花雪中送炭雨露滋润万物生长繁荣昌盛国泰民安天下太平盛世景象尽收眼底一览无余心旷神怡赏心悦目流连忘返乐此不疲废寝忘食夜以继日孜孜不倦勤学苦练精益求精百尺竿头更进一步勇攀高峰再创辉煌成就伟业名垂青史永留芳华! --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值