当前位置: 首页 > news >正文

【SystemUI】锁屏来通知默认亮屏Wake模式

一、问题描述

基于 Android 14平台,锁屏状态下来通知时默认是进入Doze模式,此时屏幕不能点击只能查看通知信息且很快灭屏,用户体验不是很好,要求修改为通知直接亮屏。

二、问题分析

梳理锁屏状态下(特指设备息屏或处于Doze/AOD状态)接收到新通知的完整流程,可以帮助您更清晰地理解代码的脉络。这个流程横跨了Android Framework的核心服务和SystemUI。

流程概览

一个App发送通知 -> NotificationManagerService (系统服务) -> SystemUI (UI进程) -> 通知中断判断 -> Doze/亮屏决策 -> 执行动作 (Pulse或WakeUp)

阶段一:通知的发送与接收
  1. 应用层 -> 系统服务层

    • App: 调用 NotificationManager.notify() 方法发送一个通知。
    • Framework (NotificationManagerService.java): 这是Android系统中负责管理所有通知的核心服务。
      • 方法: enqueueNotificationInternal()
      • 作用: 接收来自App的通知请求,进行处理、权限检查、分组、排序(Ranking)等一系列操作,然后将通知“排入队列”准备分发。
  2. 系统服务层 -> SystemUI进程

    • SystemUI (NotificationListener.java): SystemUI中有一个服务会继承 NotificationListenerService,用于监听系统中所有的通知事件。
      • 方法: onNotificationPosted(StatusBarNotification sbn)
      • 作用: 当NotificationManagerService处理完一个新通知后,会回调这个方法。这是通知进入SystemUI的第一个入口
階段二:SystemUI的内部处理与中断判断
  1. 通知信息收集与分发

    • SystemUI (NotifCollection.java) & (NotificationEntryManager.java): NotificationListener 在收到通知后,会将其传递给这些管理器。
      • 作用: 它们负责将StatusBarNotification对象包装成NotificationEntry对象,这个新对象包含了通知的所有信息和其在UI中的状态。然后,它们会将“有新通知”这个事件分发给各个监听者。
  2. 决定是否“打扰”用户(关键决策点)

    • SystemUI (NotificationInterruptStateProvider.java): 这个类是决定一个新通知是否应该发出声音、振动或**点亮屏幕(Pulse)**的核心。
      • 方法: shouldHeadsUp() / shouldPulse()
      • 作用: 它会根据通知的渠道、重要性(Importance)、用户设置(是否开启勿扰模式DND)、设备当前状态等一系列复杂的规则,来判断这个通知是否应该以“抬头通知”(Heads-Up Notification)的形式出现,或者是否应该触发一次Doze Pulse。
阶段三:从“打扰”到“亮屏”的决策传递
  1. 触发Doze Host回调

    • SystemUI (StatusBarNotificationPresenter.java) & (DozeService.java): 当NotificationInterruptStateProvider判断一个通知应该触发Pulse时,它会通过一系列调用,最终通知到DozeHost
    • 接口: DozeHost.Callback
      • 方法: onNotificationAlerted(Runnable onPulseSuppressedListener)
      • 作用: 这是一个回调方法,字面意思就是“被通知提醒了”。它标志着“有一个通知需要唤醒屏幕”这个信号正式传递到了Doze管理体系中。
  2. DozeTriggers接收信号(您正在修改的地方)

    • SystemUI (DozeTriggers.java): 这个类实现了DozeHost.Callback接口,是各种Doze触发器(传感器、通知、充电等)的集中处理地。
      • 成员: mHostCallback (一个DozeHost.Callback的实例)
      • 方法: onNotification(Runnable onPulseSuppressedListener)
      • 作用: mHostCallback在被调用时,会直接执行这个onNotification方法。这就是整个流程的汇合点,也是您进行修改的最佳位置。之前所有的判断和流程,最终都会走到这里,请求一次屏幕状态的改变。
阶段四:执行最终动作(Pulse或WakeUp)
  1. DozeTriggers.onNotification() 内部

    • 原始逻辑:
      • 方法: requestPulse(...)
      • 作用: 这个方法会请求Doze状态机执行一次“脉冲”。它内部会进一步调用proximityCheckThenCall来检查近距离传感器,如果检查通过,最终会调用mMachine.requestPulse(reason)
    • 您的修改逻辑:
      • 方法: mMachine.wakeUp(reason)
      • 作用: 这个方法会请求Doze状态机直接“唤醒”。
  2. 状态机执行命令

    • SystemUI (DozeMachine.java): 这是一个状态机,负责管理设备在INITIALIZED, DOZE, DOZE_AOD, DOZE_PULSING, FINISH等各种Doze状态之间的转换。
      • 方法: requestPulse(int reason)
        • 效果: 将状态切换到 DOZE_PULSING。这会触发DozeService在屏幕上绘制AOD通知界面,短暂亮起后熄灭。
      • 方法: wakeUp(int reason)
        • 效果: 将状态切换到 FINISH。这会退出整个Doze流程,并最终通过PowerManager完全点亮屏幕,显示锁屏界面(Keyguard)。

总结

所以,整个流程可以精简为:

NotificationManagerService.enqueueNotificationInternal()
->
NotificationListener.onNotificationPosted()
->
NotificationInterruptStateProvider.shouldPulse()
->
DozeHost.Callback.onNotificationAlerted()
->
DozeTriggers.onNotification()

三、解决方案

DozeTriggers.requestPulse() -> DozeMachine.requestPulse() -> 屏幕进入Pulse状态
DozeTriggers.mMachine.wakeUp() -> DozeMachine.wakeUp() -> 屏幕被完全唤醒

src/com/android/systemui/doze/DozeTriggers.java

private void onNotification(Runnable onPulseSuppressedListener) {// Bug #2190530 [Android14][AR.599.001744.006101.016207][SystemUI] Dimension Log Configuration for SystemUIif (UniSystemuiComponentFactory.getInstance().getDebugConfigs("DozeMachine")) {Log.d(TAG, "requestNotificationPulse");}if (!sWakeDisplaySensorState) {Log.d(TAG, "Wake display false. Pulse denied.");runIfNotNull(onPulseSuppressedListener);mDozeLog.tracePulseDropped("wakeDisplaySensor");return;}mNotificationPulseTime = SystemClock.elapsedRealtime();if (!mConfig.pulseOnNotificationEnabled(mUserTracker.getUserId())) {runIfNotNull(onPulseSuppressedListener);mDozeLog.tracePulseDropped("pulseOnNotificationsDisabled");return;}if (mDozeHost.isAlwaysOnSuppressed()) {runIfNotNull(onPulseSuppressedListener);mDozeLog.tracePulseDropped("dozeSuppressed");return;}- requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */,-         onPulseSuppressedListener);+ mMachine.wakeUp(DozeLog.PULSE_REASON_NOTIFICATION);mDozeLog.traceNotificationPulse();
}
http://www.dtcms.com/a/349927.html

相关文章:

  • Mac 菜单栏多合一工具自荐:FancyTool
  • LeetCode算法日记 - Day 22: 提莫攻击、Z字形变换
  • 电影感人文街拍摆摊纪实摄影后期Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • 从手术室到街头摄像头:多模态融合如何让AI“看得懂”万物?
  • 搭建ftp服务器(主动模式,被动模式)
  • Canvas 动态高度文本图片生成器
  • Linux 详谈Ext系列⽂件系统(一)
  • 嵌入式(ARM方向)面试常见问题及解答
  • 【ARM】MDK在debug模式下断点的类型
  • blazor 学习笔记--vscode debug
  • C++11(Linux/GCC)字节序工具
  • 2025年09月计算机二级Python选择题每日一练——第七期
  • 栈指针(Stack Pointer)是什么?
  • 设置密钥连接服务器
  • 【基础-单选】向服务器提交表单数据,以下哪种请求方式比较合适
  • Linux 离线安装lrzsz(rz、sz上传下载小插件)
  • 什么是高防服务器?如何进行防御?
  • UE5多人MOBA+GAS 54、用户登录和会话创建请求
  • 矩阵系统源代码开发,支持OEM贴牌
  • 深入解析ffmpeg.dll:电脑中的关键组件及其相关问题解决​
  • 【龙泽科技】汽车车身测量与校正仿真教学软件【赛欧+SHARK】
  • 8851定期复盘代码实现设计模式的于芬应用
  • 中国计算机学会(CCF)推荐学术会议-B(计算机图形学与多媒体):DCC 2026
  • 《信息检索与论文写作》实验报告一 EI数据库检索
  • Allegro约束管理器设置详细教程
  • JUC之volatile关键字
  • 高通平台wifi--p2p issue
  • KubeBlocks for Redis的5种网络模式
  • Linux文件归档工具tar
  • 基于SpringBoot+Vue的社区二手交易系统(WebSocket实时通讯、Echarts图形化分析、协同过滤算法)