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

相关推荐
阳光明媚sunny4 小时前
Room持久化库中,@Transaction注解的正确使用场景是?
android·数据库
Digitally4 小时前
从iPhone转移到itel手机的联系人转移指南
ios·智能手机·iphone
我是好小孩4 小时前
【Android】六大设计原则
android·java·运维·服务器·设计模式
vxtkjzxt8886 小时前
手机群控软件如何优化游戏运营的运营策略
游戏·智能手机
AORO20258 小时前
适合户外探险、物流、应急、工业,五款三防智能手机深度解析
网络·人工智能·5g·智能手机·制造·信息与通信
铉铉这波能秀9 小时前
如何在Android Studio中使用Gemini进行AI Coding
android·java·人工智能·ai·kotlin·app·android studio
川石课堂软件测试10 小时前
什么是BUG,你对BUG的了解有多少?
android·linux·服务器·python·功能测试·bug·安全性测试
vxtkjzxt88812 小时前
手机群控软件在游戏运营中的风险管控技术实现
游戏·智能手机
wanhengidc12 小时前
移动端云手机的优势都有哪些?
运维·服务器·游戏·智能手机·云计算
玩机达人8813 小时前
三星S25Ultra/S24安卓16系统Oneui8成功获取完美root权限+LSP框架
android·linux·里氏替换原则