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

相关推荐
拭心1 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
AORO_BEIDOU3 小时前
单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”
华为·智能手机·harmonyos
云云3213 小时前
搭建云手机平台的技术要求?
服务器·线性代数·安全·智能手机·矩阵
云云3213 小时前
云手机有哪些用途?云手机选择推荐
服务器·线性代数·安全·智能手机·矩阵
带电的小王4 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡4 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道4 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库5 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道6 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe6 小时前
Android Hook - 动态加载so库
android