FaceNotify 是一个基于 libxposed API 的 LSPosed 模块,专为小米 HyperOS 3 打造。实现了人脸识别成功后自动展开通知内容并停留锁屏的体验。
开启锁屏通知隐藏:系统设置-锁屏通知-显示规则(显示通知但隐藏内容)
- 系统版本:小米 HyperOS 3.0.306 (基于 Android 16 / API 36)
- 框架要求:LSPosed (支持 Zygisk/Riru)
- 作用域:系统界面 (com.android.systemui)
亮屏锁屏 -> 人脸识别成功 -> 播放成功动画和震动 -> 展开隐藏通知 -> 仍停留锁屏
上滑 -> 进入密码/指纹认证界面
息屏或睡眠 -> 恢复初始状态,下一次亮屏通知重新隐藏
核心状态是 FaceUnlockHook.isFaceUnlocked。它只表示“人脸已通过、允许锁屏通知展开”,不等价于系统已解锁。
-
接管人脸认证成功入口
Hook
com.android.keyguard.KeyguardUpdateMonitor.onFaceAuthenticated(int, boolean),在人脸成功时设置isFaceUnlocked=true,主动刷新通知,播放震动和人脸成功动画,然后不调用原始方法,从主路径阻断直接解锁。 -
展开隐藏通知
Hook
ExpandableNotificationRow.setSensitive(boolean, boolean),在人脸停留状态下把通知行改为非敏感显示。Hook
DynamicPrivacyController.isDynamicallyUnlocked(),在人脸停留状态下返回true,配合系统原有动态隐私逻辑展开通知。同时捕获
DynamicPrivacyController、SensitiveContentCoordinatorImpl和ShadeListBuilder,在人脸成功后主动触发通知列表重算,避免通知仍停留在隐藏状态。 -
阻断 HyperOS 3 的额外解锁路径
HyperOS 3.0.306 不只依赖
onFaceAuthenticated()进入桌面,还会经过小米自己的生物认证和 keyguard dismiss 路径。本模块同时处理:KeyguardUpdateMonitorInjector.isFaceUnlock():人脸停留状态下返回false,避免上滑绕过 bouncer。MiuiFaceUnlockManager.isFaceUnlockSuccessAndStayScreen():必要时返回true,让系统停留锁屏。MiuiFaceUnlockManager.isShowMessageWhenFaceUnlockSuccess()和KeyguardCommonSettingObserver.getFaceUnlockSuccessStayScreen():允许显示锁屏通知内容。BiometricUnlockControllerInjector.onBiometricAuthenticated*():仅对 FACE 来源阻断备用解锁入口,不影响指纹。BiometricUnlockController.startWakeAndUnlock(int, BiometricUnlockSource):人脸相关解锁 mode 被改为ONLY_WAKE。KeyguardViewMediator.tryKeyguardDone()/handleKeyguardDone()/handleHide():人脸停留状态下拦截隐藏锁屏,并主动显示主认证界面。
-
状态恢复
以下路径会清理
isFaceUnlocked,保证下一次亮屏通知重新隐藏:KeyguardLifecyclesDispatcher$KeyguardLifecycleHandler.handleMessage()的SCREEN_TURNING_OFF、SCREEN_TURNED_OFF、STARTED_GOING_TO_SLEEP、FINISHED_GOING_TO_SLEEP。KeyguardService$3.onScreenTurnedOff()、onStartedGoingToSleep(int)、onFinishedGoingToSleep(int, boolean)。KeyguardUpdateMonitor.mHandler的MSG_STARTED_GOING_TO_SLEEP。- 指纹认证成功和主密码认证成功路径。
app/src/main/java/com/poweran2020/facenotify/
├── ModuleMain.java
├── hooks/
│ ├── FaceUnlockHook.java
│ └── NotificationSensitiveHook.java
└── util/
└── Log.java
app/src/main/resources/META-INF/xposed/
├── java_init.list
├── module.prop
└── scope.list
features/systemui-face-unlock/
├── _index.md
├── decompiled-notes.md
└── verify-unlock-hook.sh
本地使用 JDK 17 构建:
.\gradlew.bat assembleDebug安装到已连接设备:
adb install -r app\build\outputs\apk\debug\app-debug.apk安装后需要在 LSPosed 中启用模块,并将作用域设为 com.android.systemui。
LSPosed 模块日志可用以下 tag 过滤:
FaceNotify
FaceNotify:Face
FaceNotify:Notif
关键验证点:
Hooked onFaceAuthenticatedFace authenticated, blocking unlockNotification refresh requestedScreen off (...) -> resetting face state
GSWXXN/Notiface。Notiface 提供了“人脸识别后停留锁屏并展开通知”的核心思路;本项目在此基础上针对 HyperOS 3.0.306 / Android 16 的 SystemUI、Keyguard 和通知流水线差异做了重新实现与适配。
LSPosed/LSPosed。 LSPosed 提供Hook能力