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

相关推荐
夜未央ぴ陌上花开丶9 分钟前
Android mqttv5
android
草明11 分钟前
AndroidManifest.xml 文件中的 package 属性不再是强制要求定义
android·xml·react native
匆忙拥挤repeat1 小时前
Android 简单实现联系人列表+字母索引效果
android
Studying 开龙wu2 小时前
4.3章节python中循环结构:两种类型:for 循环和 while 循环用法
android·java·python
招风的黑耳3 小时前
Android页面跳转与返回机制详解
android
techSista3 小时前
华为FreeBuds 6i怎么佩戴不容易掉?
华为·智能手机·音视频
@月落4 小时前
PHP爬虫淘宝商品SKU详细信息获取指南
android·爬虫·php
韩家老大5 小时前
Failed to load WebView provider: No WebView installed
android
阿豪元代码5 小时前
Perfetto 快速上手指南
android