android锁屏界面userActivity自动息屏深入剖析

背景:

近来有有个学员朋友在锁屏画面自动息屏有一些疑问求助马哥这边,大致情况描述如下:

问题1、锁屏画面不停的点击触摸发现锁屏画面会一直常亮,这里他知道锁屏这个window比较特殊,正常其他window在InputDispatcher进行事件传递时候都会进行userActivity时间的更新,但是锁屏画面是有屏蔽userActivity操作,所以认为锁屏画面哪怕一直点击也不应该阻止息屏

问题2、锁屏画面有时候一直触摸按着界面发现也会自动的息屏,认为这个是不是一个bug

首先大家得有一点预备知识:

那就是手机为了整体功耗,其实是有对手机设置一个自动进入息屏的时间,就是手机在一段时间没有任何触摸等操作时候,手机会进行变暗,灭屏。这样目的就是为了节省功耗延迟手机的使用时间。一旦亮屏时候有用户触摸手机屏幕,那么肯定进入息屏的时间就需要从手机最后触摸时间开始计算,这里手机触摸后就会触发userActivity方法,跨进程到pms中进行统计时间的更新。

有了上面的知识背景后接下来在开始对学员提出的问题进行挨个解释分析。

问题1剖析

锁屏画面window相比普通的window有啥不一样么?这里的对于手机自动息屏部分有啥差异呢?

要查看window之间在input部分的差异最好就是看dumpsys input相关输出:

这里输出太多,就拿NotificationShade锁屏窗口和状态栏窗口StatusBar来进行对比看看

bash 复制代码
 1: name='728a9f0 NotificationShade', id=663, displayId=0, inputConfig=TRUSTED_OVERLAY | WATCH_OUTSIDE_TOUCH | DISABLE_USER_ACTIVITY, alpha=1.00, frame=[0,0][1080,1920], globalScale=1.000000, applicationInfo.name=, applicationInfo.token=<null>, touchableRegion=[-1080,-1920][2160,3840], ownerPid=12201, ownerUid=10143, dispatchingTimeout=5000ms, hasToken=0x7702fa8350, touchOcclusionMode=BLOCK_UNTRUSTED
        transform (ROT_0) (IDENTITY)
      2: name='8fb1249 StatusBar', id=285, displayId=0, inputConfig=NOT_FOCUSABLE | TRUSTED_OVERLAY, alpha=1.00, frame=[0,0][1080,74], globalScale=1.000000, applicationInfo.name=, applicationInfo.token=<null>, touchableRegion=[0,0][1080,74], ownerPid=12201, ownerUid=10143, dispatchingTimeout=5000ms, hasToken=0x7702fa8490, touchOcclusionMode=BLOCK_UNTRUSTED
        transform (ROT_0) (IDENTITY)

明显可以NotificationShade的inputConfig有一个DISABLE_USER_ACTIVITY属性,这个属性就是它的特别之处相比于其他window,grep DISABLE_USER_ACTIVITY寻找相关线索:
可以大致看出在这个DISABLE_USER_ACTIVITY在java层面创建window其实是INPUT_FEATURE_DISABLE_USER_ACTIVITY这个属性进行配置和设置。

frameworks/base/core/java/android/view/WindowManager.java

cpp 复制代码
        /**
         * When this window has focus, does not call user activity for all input events so
         * the application will have to do it itself.  Should only be used by
         * the keyguard and phone app.
         * <p>
         * Should only be used by the keyguard and phone app.
         * </p>
         *
         * @hide
         */
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 1 << 1;

注释可以看出了,当window有焦点时候,所有输入事件都不会调用userActivity方法来更新最后的活跃时间,需要app自己来控制这个活跃时间。使用该flag也只能是keyguard和phone app。

那么对应InputDispatcher部分对这个flag处理如下:

那么问题来了,既然NotificationShade输入事件是不会进行调用userActivity到power更新时间,那么为啥不停的点击时候,手机不会自动息屏?

这个问题要解答就需要去userActivity方法中打印日志堆栈,或者抓取trace来分析:

到userActivity方法加入堆栈如下:

发现在点击NotificationShade确实有调用这个userActivity方法

bash 复制代码
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: java.lang.Exception
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at android.os.PowerManager.userActivity(PowerManager.java:1482)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at android.os.PowerManager.userActivity(PowerManager.java:1447)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at com.android.systemui.keyguard.KeyguardViewMediator.userActivity(go/retraceme 82fd227f7994cdb56e784cec6bfccc2f9340b959741c421f19a58b2a7c6f0476:13)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at com.android.systemui.shade.NotificationPanelViewController$TouchHandler.onInterceptTouchEvent(go/retraceme 82fd227f7994cdb56e784cec6bfccc2f9340b959741c421f19a58b2a7c6f0476:978)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at com.android.systemui.shade.NotificationPanelView.onInterceptTouchEvent(go/retraceme 82fd227f7994cdb56e784cec6bfccc2f9340b959741c421f19a58b2a7c6f0476:3)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2657)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at com.android.systemui.shade.NotificationPanelView.dispatchTouchEvent(go/retraceme 82fd227f7994cdb56e784cec6bfccc2f9340b959741c421f19a58b2a7c6f0476:1)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3123)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2747)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at com.android.systemui.shade.NotificationShadeWindowView.dispatchTouchEvent(go/retraceme 82fd227f7994cdb56e784cec6bfccc2f9340b959741c421f19a58b2a7c6f0476:824)
09-27 00:28:18.947 12201 12201 I PowerManagerSerivce: 	at android.view.View.dispatchPointerEvent(View.java:15928)

根据堆栈查看到相关方法:

frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java

这里其实就能理解上面的注释,InputDispatcher中虽然已经屏蔽了userActivity,但是app可以自己根据情况控制userActivity的调用。这里发现确实只在down事件有调用,但是其他move等事件没有调用,所以这里可以解释清楚,锁屏画面时候一定要不停地点击画面才可以保持不会自动进行息屏。

问题2剖析

有了问题1的结论,即NotificationShade窗口只会在down事件时候发送userActivity,那么意味着其他事件不会发送userActivity,所以经过测试结果如下:

只要触摸按下后一直停留在NotificationShade窗口进行移动,移动事件根本不会调用userActivity,所以到了自动息屏时间后一样会进行息屏,因为除了down事件,其他事件根本不会对进行userActivity更新自动息屏时间。

更多framework详细代码和资料参考如下链接

投屏专题部分:
https://mp.weixin.qq.com/s/IGm6VHMiAOPejC_H3N_SNg

hal+perfetto+surfaceflinger

https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg

其他课程七件套专题:

点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频试看:
https://www.bilibili.com/video/BV1wc41117L4/

参考相关链接:

https://blog.csdn.net/zhimokf/article/details/137958615

更多framework假威风耗:androidframework007

相关推荐
Starry-sky(jing)4 小时前
Vidda ADB 开启:R Pro 65 找不到开发者选项的处理与连接验收
android·adb·远程控制·电视·vidda
雨白5 小时前
从原理到实践:使用 Kotlin KSP 仿写 ButterKnifeLite
android·kotlin
疯华整猫6 小时前
把二十七个 init 从首帧前面搬走:用 Trae 把启动优化钉进 CI
android·性能优化·ai编程
传奇开心果6 小时前
【探秘 Jetpack Compose 框架深水区】 第8课:rememberSaveable 的边界在哪里?——Bundle、Saver 与什么值得跨进程存活
android·kotlin
Frankie_stand7 小时前
测试自动化实战指南:从脚本化、自动判据到 CI 集成的完整落地路径
android·ci/cd·自动化
恋猫de小郭8 小时前
Flutter 大小核优化又被回滚,然后又开新提案?
android·前端·flutter
Kapaseker8 小时前
领导问我 Kotlin 的 Nothing 是什么?
android·kotlin
韩曙亮9 小时前
【错误记录】安卓 adb 调试 5037 端口占用排查 ( adb 的三层结构 | 找出本机占用 5037 的进程 )
android·数据库·adb·安卓·错误记录
三少爷的鞋10 小时前
不改变异步本质,只改变代码组织:Telegram 项目的 Kotlin 协程实践
android
好的佩奇19 小时前
蓝牙之广播与扫描
android·flutter·蓝牙