• 全新单提交:清除含敏感信息的旧历史(sudo 口令、内网 IP、SSH 密钥路径、热点 SSID、设备 MAC) • 本地开发文档/测试记录/构建脚本全部移入 gitignored 的 devdocs/ 与 scripts/build/(不入库) • 保留:MeowOS 源码(launcher/watchdog/bootmenu/meow_svcd/SDK)、项目规范文档、mips-repo 增补组件:SDK 统一日志+通知 API、meow_svcd 服务管理器、mips-repo 软件仓库
102 lines
8.7 KiB
Markdown
102 lines
8.7 KiB
Markdown
# MeowOS 全面按键接管设计(Key Control)
|
||
|
||
> 状态:已落地(M2.24,2026-08-29,见 §9 落地记录)。目标:**所有按键信号全部由系统接管**,任何界面(launcher 菜单 / MeowAPP / 息屏)都统一响应系统语义。应用侧绝不碰物理键(APPS.md §3.4.1 规范)。本设计是「全面按键接管专项」的蓝本。
|
||
|
||
---
|
||
|
||
## 1. 原则
|
||
|
||
1. **按键是系统资源**,语义由系统组件(launcher / watchdog / 内核)统一决定。
|
||
2. **任何界面按键行为一致**:电源=息屏/长按菜单、音量=系统音量、播放/上下曲=活跃媒体会话(现阶段先"抓住"不路由)。
|
||
3. **应用绝不映射物理键**:MeowAPP 只接收 SDK 语义事件(tap/swipe/tick),不读 `/dev/input`、不把任何物理键映射成确认/exit/返回/翻页。只有 MeowOS 界面(launcher 菜单/选单/电源菜单)允许处理物理键语义。
|
||
|
||
## 2. 按键 → 系统行为映射表(所有界面统一)
|
||
|
||
| 键 | code | 系统行为 | 现阶段 | 依赖 |
|
||
|---|---|---|---|---|
|
||
| 电源 单击 | 116 | 息屏/亮屏 | ✅ 实现(watchdog 接管) | 无 |
|
||
| 电源 长按 3s | 116 | 打开电源菜单(关机/重启/回HibyOS/取消) | ✅ 实现 | 无 |
|
||
| 电源 长按 8s | 116 | 强制关机 | ✅ 实现 | 无 |
|
||
| 音量 + | 115 | 调系统音量(CS43198 DAC) | ✅ 实现 | 无 |
|
||
| 音量 − | 114 | 调系统音量 | ✅ 实现 | 无 |
|
||
| 播放/暂停 | 164 | 活跃媒体会话 播放/暂停 | 🔵 **先抓住(不泄漏给应用)** | 阶段D媒体会话 |
|
||
| 上一曲 | 165 | 活跃媒体会话 上一曲 | 🔵 **先抓住** | 阶段D媒体会话 |
|
||
| 下一曲 | 163 | 活跃媒体会话 下一曲 | 🔵 **先抓住** | 阶段D媒体会话 |
|
||
|
||
> 🔵 “先抓住”:watchdog 捕获该键信号并**消费掉**(记录日志、暂不执行动作),确保不泄漏给 MeowAPP(防止应用误用/误响应),也不产生"按键被吞"的观感空洞。等阶段 D 媒体会话落地,在**同一点**直接转给活跃会话(无需改键处理层)。
|
||
|
||
## 3. 实现:统一监听点
|
||
|
||
**关键**:所有界面的按键语义集中在**一个常驻系统组件**里判断,不分散。
|
||
|
||
- **launcher 菜单/列表界面**:已有 `run_menu` 主循环读键(音量/电源/播放)。**保留**,作为 MeowOS 界面的键处理。
|
||
- **MeowAPP 运行界面**:launcher 卡在 `waitpid(app)`,主循环不跑 → **由 `meow_watchdog` 接管按键**(watchdog fork 出来陪跑 app、读 `/dev/input/event*`)。
|
||
- **共同原则**:watchdog 与 launcher 用**同一套按键语义逻辑**(电源单击=息屏、长按=菜单、音量=调音量、播放/上下曲=抓住/路由),从代码层面保证"任何界面一致"。
|
||
|
||
### watchdog 按键语义(应用运行期,重点新增)
|
||
watchdog 主循环(`for(;;)`)加按键轮询(`read /dev/input/event0/event2`):
|
||
- **KEY_POWER(116)**:
|
||
- 按下计时,≤某阈值单击 → 息屏/亮屏(复用 launcher `meow_panel_off/on`:背光 0 + FBIOBLANK(4) / FBIOBLANK(0)+亮度恢复);
|
||
- 按住 ≥3s → 电源菜单(复用 launcher 的电源菜单 UI/逻辑——但 watchdog 是独立进程,需把电源菜单绘制/交互自包含,或经 IPC 通知 launcher);**为避免双进程抢屏,建议:watchdog 把"长按电源"事件经 IPC 上报 launcher,由 launcher 弹电源菜单**(launcher 仍在 waitpid 但可被 eventfd 唤醒处理菜单)。
|
||
- 按住 ≥8s → 强制关机(`syscall(SYS_reboot, ...POWER_OFF)`)。
|
||
- **KEY_VOLUMEUP(115) / KEY_VOLUMEDOWN(114)** → 调系统音量(复用 launcher 的 `settings_volume_adj` / CS43198 DAC 写路径)。
|
||
- **KEY_PLAYPAUSE(164) / KEY_PREVIOUSSONG(165) / KEY_NEXTSONG(163)** → **先抓住**:捕获、logmsg、消费,暂不路由;媒体会话落地后转活跃会话。
|
||
- **KEY_PREVIOUS(19)**:`KEY_PREVIOUSSONG` 是 165;19 是另一码(`KEY_PREVIOUSSONG` 统一用 165,见 launcher `DEV_POWER` 注释 event0 含 POWER/PREVIOUS)。
|
||
|
||
## 4. 电源菜单在应用内如何弹出(关键设计决策)
|
||
|
||
应用运行时 watchdog 捕获长按电源。电源菜单**由谁画**?两方案:
|
||
- **方案 A(推荐)**:watchdog 长按 3s → 写 `/tmp/meowapp_state`/或 SIGUSR1 通知 → **launcher 从 waitpid 被 eventfd 唤醒 → SIGSTOP app → 弹电源菜单**(复用 launcher 现有电源菜单代码,不重复实现)。菜单关闭 → SIGCONT app。
|
||
- 方案 B:watchdog 自绘电源菜单(独立实现,重复代码,且与 launcher 抢屏时序复杂)。
|
||
|
||
**选 A**:电源菜单始终由 launcher 统一绘制(一处实现),watchdog 只负责"检测到长按电源→唤醒 launcher"。这符合"系统接管要统一、不分散"。
|
||
|
||
## 5. 与应用/将来会话的衔接
|
||
|
||
- **现阶段**:播放/上下曲"抓住"(消费日志,不路由)。应用拿不到这些键 → 不会误操作。
|
||
- **阶段 D**:媒体会话(`MSG_REGISTER svc=media_session` / `MF_PLAYBACK`,见 FRAMEWORK_DESIGN §5/附录 B)落地后,**在 watchdog 抓住键的同一点**直接 `route_to_active_media_session()`。键处理层结构不变,只加路由调用。
|
||
|
||
## 6. 涉及文件
|
||
|
||
| 文件 | 改动 |
|
||
|---|---|
|
||
| `patch_v2/meow_watchdog/meow_watchdog.c` | 主循环加按键轮询:电源(单击息屏/长按菜单/8s关机)、音量(调音量)、播放/上下曲(抓住);长按电源 → 唤醒 launcher |
|
||
| `patch_v2/meow_launcherd/meow_launcherd.c` | 应用运行时(waitpid 中)能被 eventfd 唤醒处理电源菜单;复用现有电源菜单/panel/音量逻辑 |
|
||
| `patch_v2/sdk/meow_ui_input.c` | 不接管物理键语义(仅触摸 tap/swipe),排除误读事件1以外的键 |
|
||
| `APPS.md §3.4.1` | 已写规范(应用禁映射物理键)——保持 |
|
||
| `FRAMEWORK_DESIGN.md` | 阶段 D 媒体会话:播放/上下曲路由到活跃会话(附录 B) |
|
||
|
||
## 7. 真机验收(用户)
|
||
|
||
1. 应用内:电源键**单击=息屏、长按 3s=电源菜单、长按 8s=关机**;
|
||
2. 应用内:音量 ± = 调音量(状态栏可见);
|
||
3. 应用内:播放/上一曲/下一曲**不引起应用任何反应**(被系统抓住);
|
||
4. launcher 菜单 / 应用列表:同样电源/音量行为一致;
|
||
5. 电源菜单在任何界面都能弹出(含应用内);
|
||
6. 息屏后任意键唤醒。
|
||
|
||
## 8. 依赖与顺序
|
||
|
||
- **前置**:agent-46(应用输入接管修复,电源键息屏奠基)完成。
|
||
- **本轮**:全面按键接管专项(✅ 已落地 M2.24:watchdog 全键接管 + launcher 唤醒弹电源菜单 + 播放键抓住)。
|
||
- **下期**:阶段 D 媒体会话 → 播放/上下曲路由。
|
||
|
||
*本设计为蓝本,实现以代码注释+KEY_CONTROL_DESIGN.md 为准;与 APPS.md §3.4.1、FRAMEWORK_DESIGN §5/附录 B 对齐。*
|
||
|
||
## 9. 落地记录(M2.24,2026-08-29,MeowOS 0.7.19)
|
||
|
||
完成项(相对本蓝本):
|
||
- ✅ 电源 单击=息屏/亮屏:`meow_watchdog.c handle_power`(沿用 M2.22,短按<3s)。
|
||
- ✅ 电源 长按≥3s=电源菜单:`meow_watchdog.c wd_power_tick` 写 `/tmp/meow_power_menu` → `meow_launcherd.c` 应用 waitpid 轮询消费 → `SIGSTOP app` + 写 `/tmp/meow_power_menu_active` → `show_power_menu()`(launcher 一处绘制)→ 关菜单清标记 → `SIGCONT app`。方案 A。
|
||
- ✅ 音量±:`meow_watchdog.c wd_vol_adj` 自实现(写 CS43198 amixer numid=1/2 + 持久化 `/usr/data/meow/settings.conf` 与 launcher 同源);launcher `launch_app` 末尾 `settings_load()` 刷新。
|
||
- ✅ 播放/上下曲(164/165/163/19):`meow_watchdog.c` 捕获+日志+消费,不路由;SDK `meow_ui_input.c` 吞噬全部物理键,应用绝不碰。
|
||
- ✅ 应用内电源菜单弹出中断恢复:`show_power_menu` 复用(含触摸/音量导航/电源确认/8s 强关/pm_interacted 保护)。
|
||
|
||
偏差(实现以稳妥为准,记录如下):
|
||
1. **8s 强关拆分**:设计给 watchdog,但为避免与菜单内 `pm_interacted` 冲突(用户正点选时被强关抢先),落地为「launcher 菜单内 8s 强关(pm_interacted 保护)+ watchdog 8s 兜底(仅当菜单未接管,即 `/tmp/meow_power_menu_active` 未出现)」。
|
||
2. **音量跳步**:watchdog 每按下边沿按 `audio.volume_step` 一步(不做 launcher 的线性渐变);短按与 launcher 菜单一致,长按不连续爬(媒体落地后可补)。launcher 应用返回时 `settings_load()` 同步。
|
||
3. **左右滑切屏**:菜单触摸段已留 `menu swipe (dx,dy) — no launch` 判定,未实现切换逻辑。
|
||
4. **媒体键**:仅抓消费(日志 `media key captured (code N) -> consumed, no route`),路由待阶段 D。
|
||
|
||
真机验收要点(§7):应用内电源单击/长按菜单/8s 强关、音量±调音量、播放/上下曲无反应(被抓住)、launcher 菜单同样一致、电源菜单任何界面可弹(含应用内)、息屏后任意键唤醒。
|