安卓如何实现双击触摸唤醒点亮屏幕功能-Android framework实战开发

背景

经常有学员朋友在群里问到一个目前市场上常见的功能:

手机待机时候双击屏幕可以唤醒点亮手机屏幕功能

如何实现这个功能,经常有同学在群里求助,今天就刚好来讨论一下这个待机时候双击触摸唤醒点亮屏幕的功能的实现方案。

功能核心方案设计:

正常息屏待机时候,通过getevent是无法获取到任何的触摸事件,因为这个时候触摸屏驱动是没有工作,不会上报,需要息屏时候实现实现对触摸事件的输入,那么就需要考虑如何在息屏时候让触摸运行起来,这里一般可能会想到如下2个方案:

方案1、整体的息屏就是个假息屏,即息屏其实本质就是让背光关闭,但是触摸和画面等是可以正常使用,即这个息屏待机其实仅仅是背光关闭而已,但是系统app,触摸等都是正常运行的,只是没有背光看着屏幕息屏而已,这种其实整体功耗相比原来的息屏就会大很多。

方案2、息屏是正常的息屏,整体app画面也进入待机模式,不会在绘制画面等,背光也是关闭的,但是触摸驱动这个是上电的,可以识别用户的触摸事件,驱动层面识别双击后触发点亮屏幕。

下面针对2个方案进行尝试性调研

方案1可以直接framework层面修改

因为所有的power按键逻辑处理,都是需要经过PhoneWindowManager这里类进行的。所以考虑是否可以在PhoneWindowManager中对原有的power进行待机和唤醒操作进行修改。

核心思路步骤如下:

1.需要对power按键的原有息屏亮屏处理逻辑都进行屏蔽,即先让power按键按了之后没有任何反应

2.再针对power按键进行新的逻辑处理,只需要添加背光设置操作,息屏背光设置为0,亮屏恢复正常背光值

cpp 复制代码
   public static  boolean isScreenLightOff = false;
    void setLightOff(){
        LightsManager lights = LocalServices.getService(LightsManager.class);
        LogicalLight mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
        isScreenLightOff =true;
        mBacklight.setBrightness(0);
    }

    void setLightOn(){
        LightsManager lights = LocalServices.getService(LightsManager.class);
        LogicalLight mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
        int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS,
                mPowerManager.getDefaultScreenBrightnessSetting(),UserHandle.USER_CURRENT_OR_SELF);
        isScreenLightOff =false;
        mBacklight.setBrightness(brightness);
    }

3、需要对触摸事件进行的相关的识别,让触摸事件在背光为0状态不进行派发到任何的app,只是在InputDispatcherh中进识别双击,如果一旦双击则重新调用setLightOn,让屏幕点亮

该方案总结:

1、这个修改波及很大,修改了很多的原生逻辑,很多时候也有其他逻辑修改相关的背光情况,经常可能出现修改不全等情况

2、因为本质只是关闭了背光而已,所以整体app都还在正常运行,没有进入待机状态,所以整体功耗肯定比以前大很多

方案1缺点都比较致命,所以基本上完全不推荐该方案

方案2 驱动层面实现

这个方案属于大部分厂商都使用的现成方案,具体代码和实现细节暂时不进行深入,这里可拿相关手机来进调研看看是如何做到的。

1、有一个设置开关来启动双击亮屏功能

打开后既可以实现在灭屏时候点击触摸屏幕2下既可以点亮

2、在灭屏时候连续点击屏幕两下,通过getevent看看是不是传递的触摸事件?

bash 复制代码
test@test:~/disk2/nx563j_aosp14$ adb shell getevent -lrt
add device 1: /dev/input/event8
  name:     "msm8998-tasha-snd-card Button Jack"
add device 2: /dev/input/event7
  name:     "msm8998-tasha-snd-card Headset Jack"
add device 3: /dev/input/event6
  name:     "uinput-fpc"
add device 4: /dev/input/event1
  name:     "proximity"
add device 5: /dev/input/event2
  name:     "light"
add device 6: /dev/input/event0
  name:     "qpnp_pon"
add device 7: /dev/input/event3
  name:     "hall_device"
add device 8: /dev/input/event4
  name:     "nubia_synaptics_dsx"
add device 9: /dev/input/event5
  name:     "gpio-keys"
[  485422.726460] /dev/input/event4: EV_KEY       KEY_WAKEUP           DOWN                
[  485422.726460] /dev/input/event4: EV_SYN       SYN_REPORT           00000000            
[  485422.726758] /dev/input/event4: EV_KEY       KEY_WAKEUP           UP                  
[  485422.726758] /dev/input/event4: EV_SYN       SYN_REPORT           00000000             rate 3355
[  485422.791717] /dev/input/event1: EV_REL       REL_RZ               0000000a            
[  485422.791717] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             rate 15
[  485422.878681] /dev/input/event1: EV_REL       REL_RZ               0000000a            
[  485422.878681] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             rate 11

明显可以看出getevent获取的数据这里根本没出现有任何的触摸事件的abs数据,而是变成的KEY_WAKEUP的Key事件类型,从而达到唤醒屏幕的目的,这个KEY_WAKEUP就是和正常按下POWER按钮事件一样。

正常Power的getevent展示如下:

bash 复制代码
[  485662.684341] /dev/input/event0: EV_KEY       KEY_POWER            DOWN                
[  485662.684341] /dev/input/event0: EV_SYN       SYN_REPORT           00000000            
[  485662.801875] /dev/input/event1: EV_REL       REL_RZ               0000000a            
[  485662.801875] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             rate 8
[  485662.827897] /dev/input/event0: EV_KEY       KEY_POWER            UP                  
[  485662.827897] /dev/input/event0: EV_SYN       SYN_REPORT           00000000             rate 38

KEY_WAKEUP和KEY_POWER的主要区别在于它们的功能和用途不同。‌

KEY_WAKEUP通常用于在设备休眠状态下通过特定按键唤醒设备,而KEY_POWER则用于控制设备的开关机功能。

KEY_WAKEUP是一个特定的按键值,用于在设备休眠时通过中断唤醒设备。当设备处于休眠状态时,通过按下具有唤醒功能的按键(如PowerKey),会触发中断,从而唤醒设备。这与设备的电源管理密切相关,允许用户在不完全关闭设备的情况下快速恢复使用‌12。

KEY_POWER则是指用于开关机的按键,通常在设备完全关闭时使用。按下KEY_POWER键会触发设备的关机或重启过程,这与设备的启动和关闭操作直接相关‌24。

在技术实现上,KEY_WAKEUP通常与设备的输入系统(如GPIO)相关联,并在设备休眠时设置为中断源。当按键被按下时,会触发中断,从而使设备从休眠状态唤醒。而KEY_POWER键的实现则涉及到更底层的硬件控制,确保设备能够执行开关机操作‌12。

即无论WAKEUP还是POWER都可以唤醒休眠点亮屏幕。
方案总结:

驱动层面实现方案为啥成为各个厂商主流方案,主要有以下几点:

1、完全不需要修改任何的framework层面代码,不需要修改破坏任何的原生power逻辑

2、驱动部分直接就识别了双击,然后上报的一个KEY_WAKEUP事件,非常简单的实现了唤醒设备

更多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 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android