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

    2025-09-28 02:58:39

    背景

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

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

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

    功能核心方案设计:

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

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

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

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

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

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

    核心思路步骤如下:

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

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

    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看看是不是传递的触摸事件?

    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展示如下:

    [ 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技术干货,请关注下面“千里马学框架”