当前位置: 首页 > news >正文

面试题剖析:android全局触摸事件的前世与今生InputMonitor/SpyWindow

背景:

昨天整理分享了惊奇学员们零零散散给我发过的一些面试题目:
安卓系统fw工程师面试福利9:近期收集学员手机车载FW面试真题

有vip学员朋友在群里对12题进行了讨论:

在这里插入图片描述他的回答如下:

在这里插入图片描述这个同学回答其实还是比较认真的,他认为因为以前的Monitor是只有systemserver进程才可以进行监听的,所以要系统app可以监听全局触摸必须要sypwindow才可以,其实这个回答还是不那么准确哈。
这个面试题目如果要想回答好,其实还是需要对全局触摸事件监听的历史发展版本有一个深入的了解才可以,本文将针对触摸事件的全局监听这块前世与今生进行剖析。

低版本安卓10-12全局InputMonitor方式(前世)

android 10版本的全局事件监听实现:
frameworks/base/core/java/android/hardware/input/InputManager.java

  /*** Monitor input on the specified display for gestures.** @hide*/public InputMonitor monitorGestureInput(String name, int displayId) {try {return mIm.monitorGestureInput(name, displayId);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

   /*** Creates an input monitor that will receive pointer events for the purposes of system-wide* gesture interpretation.** @param inputChannelName The input channel name.* @param displayId Target display id.* @return The input channel.*/@Override // Binder callpublic InputMonitor monitorGestureInput(String inputChannelName, int displayId) {if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,"monitorInputRegion()")) {throw new SecurityException("Requires MONITOR_INPUT permission");}Objects.requireNonNull(inputChannelName, "inputChannelName must not be null.");if (displayId < Display.DEFAULT_DISPLAY) {throw new IllegalArgumentException("displayId must >= 0.");}final long ident = Binder.clearCallingIdentity();try {InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);InputMonitorHost host = new InputMonitorHost(inputChannels[0]);inputChannels[0].setToken(host.asBinder());nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId,true /*isGestureMonitor*/);return new InputMonitor(inputChannelName, inputChannels[1], host);} finally {Binder.restoreCallingIdentity(ident);}}

注册后使用dumpsys input可以展示如下:
在这里插入图片描述

在这里插入图片描述

高版本安卓13及以上更新成了SpyWindow方式 (今生)

android 13版本的全局事件监听实现:
frameworks/base/core/java/android/hardware/input/InputManager.java

   /*** Monitor input on the specified display for gestures.** @hide*/public InputMonitor monitorGestureInput(String name, int displayId) {try {return mIm.monitorGestureInput(new Binder(), name, displayId);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}

服务端system_server实现
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

    /*** Creates an input monitor that will receive pointer events for the purposes of system-wide* gesture interpretation.** @param requestedName The input channel name.* @param displayId Target display id.* @return The input channel.*/@Override // Binder callpublic InputMonitor monitorGestureInput(IBinder monitorToken, @NonNull String requestedName,int displayId) {final long ident = Binder.clearCallingIdentity();try {final InputChannel inputChannel =createSpyWindowGestureMonitor(monitorToken, name, displayId, pid, uid);return new InputMonitor(inputChannel, new InputMonitorHost(inputChannel.getToken()));} finally {Binder.restoreCallingIdentity(ident);}}

使用dumpsys input看看输出情况:
在这里插入图片描述

剖析SpyWindow是个啥?

解释这个还是使用官方的注释比较全面
frameworks/base/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java
在这里插入图片描述

/*** An internal implementation of an {@link InputMonitor} that uses a spy window.** This spy window is a layer container in the SurfaceFlinger hierarchy that does not have any* graphical buffer, but can still receive input. It is parented to the DisplayContent so* that it can spy on any pointer events that start in the DisplayContent bounds. When the* object is constructed, it will add itself to SurfaceFlinger.*/

上面注释简总结如下:
1、 spy window是一个SurfaceFlinger中的layer,但是layer没有任何图像内容显示

2、但是这个layer是可以监听当前displaycontent所有输入事件

为什么用SpyWindow替代InputMonitor思考?

以下属于个人观点:
先看看二者差异及共同点
共同点:
二者都可以实现对全局事件的监听,即display上的所有事件都可以监听到

差异:
InputMonitor其实是直接在InputDispatch中有InputChannel,直接InputDispatcher的所有输入事件发送到这个InputChannel,没有任何的InputWindow的相关信息,完全是单独属于global monitor处理

Spy Window属于和其他普通的InputWindow没啥区别,InputWindow类型是SPY,InputDispatcher在派发窗口收集时候识别SPY后会进行优先放入。

为啥要升级为SpyWindow抛弃原来的InputMonitor方式
因为这块没有找到google官方的一个说明,所以下面的都是个人观点(大家有其他观点也可以留言讨论哈):

遵守统一
Spy Window 完全遵守现有的窗口管理和输入分发规则,InputDispatcher 以完全相同的方式处理它和普通应用窗口。

Monitor 的一些痛点问题
Monitor 可能无法完全感知到窗口的瞬时状态如窗口关闭,那么还需要注册InputMonitor一定记得注销,不然可能导致错误的拦截决策,但是变成窗口了那就统一不需要额外关注。

原文参考:
https://mp.weixin.qq.com/s/Dp0GvB50qowA1OpuO2tfFA

更多framework实战开发干货,请关注下面“千里马学框架”

http://www.dtcms.com/a/577911.html

相关文章:

  • 【HarmonyOS-北向开发(软件)】
  • 20251106给荣品RD-RK3588-MID开发板跑Rockchip的原厂Android13系统时禁止锁屏+永不休眠
  • 深入理解 SELinux:架构、概念与基本操作
  • 用vs2010做网站论文深圳市专业制作网站公司
  • 国土资源局加强网站建设wordpress 栏目 伪静态化
  • XMAU7118_VC1:16通道PDM到I²S/TDM音频转换器产品介绍
  • 云手机 轻松畅玩云端游戏
  • 认证空间官方网站附子seo教程
  • 网络层协议 - ICMP
  • DINO系列粗读
  • Java设计模式精讲---03建造者模式
  • P3384 【模板】重链剖分/树链剖分
  • OpenCV(二十):位运算
  • 重组蛋白纯化标签科普:从His到SUMO、Avi的全面解析
  • 【QT第三章】常用控件1
  • 鱼台做网站多少钱wordpress 防黑
  • 南通网站建设排名公司网站怎么做图片放映效果
  • AI Agent:突破工作流局限,开启智能决策新时代
  • 自己动手写深度学习框架(神经网络的引入)
  • 西安专业网站建设服务好查询食品注册商标查询官网
  • ref对比reactive
  • 基于融智学双重形式化的汉字汉语数学建模方法
  • 手机wap网站多少钱wordpress页面简码
  • 嘉兴网嘉兴网站建设网址大全汽车之家官方网
  • 基于单片机的智能高温消毒与烘干系统设计
  • vue.js设计与实现(待续)
  • 2025 Vue UI 组件库选型
  • 网站内置字体法治网站的建设整改措施
  • 杭州高端网站设计南宁伯才网络建站如何
  • 面试题001