Files
MeowOS-For-R3P2/KEY_CONTROL_DESIGN.md
T
MeowOS ab4dfb4f9c docs: 文档一致性整理 (agent-265) — 对齐 M2.91-96/0.7.86-0.7.91 + 261/262/264
- README: 版本头 M2.90→M2.96;M2.91-96 批次( audiod FPGA 开机武装根治 PCM 死锁 / 充电权威链 mp2731 / amsd 注册自愈 / NP 死循环修复+充电闪电 / 插孔消抖三路 / 长流护栏+几何 period=1024×4 / wd_vol_save 毁设置修复 / 音量反转四路统一 dac=255-pct*255/100 / 炸耳修复 dac_vol_mute=255 );流媒体客户端三期续(254 滑窗/256 封面缓冲 UX/260 FLAC dr_flac/262 播放键 toggle);已知问题 PCM 挂死条目移除(已根治)
- MEOW_APP_SDK §5.9: 后续批次全量(FPGA 武装/长流护栏+几何/音量反转+炸耳修复/261 电平监控 rms/peak+monitor CLI, ABI 兼容);IME 节后注拼音 IME 已落地
- FRAMEWORK_DESIGN: 头部里程碑 M2.15-M2.96;附录 B PLAYCTL 补 cmd=6 toggle
- SPEC_REF: §4 audiod 条目补 M2.91-97 加固批;音频硬件事实补衰减量语义+端口 5=audiod 强制重烧约定;现行版本 0.7.91(261 待 M2.97);252 面板 /api/audio+字体页;OPEN_QUESTIONS 待定批更新(PCM 挂死已清结)
- SYSTEM_SETTINGS: audio.volume 衰减量注记 + 音量存盘读改写单键纪律
- KEY_CONTROL §9: SDK 插孔消抖已落地(56c569f) + 音量反转/存盘修复 + 262 播放键 cmd=6 toggle
- APPS §3.7: audiod 加固批摘要 + 262 toggle
- DEVELOPMENT_PLAN: 头部截至 M2.96
- 口径: 入库文档应用名统一中性表述「流媒体客户端(dev.player.ncm)」
2026-09-01 15:41:33 +08:00

105 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/app_launcher.c`(`launch_app` waitpid 循环) | 应用运行时(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` → `app_launcher.c`(`launch_app` waitpid 循环)消费 → `SIGSTOP app` + 写 `/tmp/meow_power_menu_active` → `power_menu.c 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. **左右滑切屏**:**已落地(M2.81 Now Playing 横划页)**——主界面左滑进 Now Playing 大页;左缘返回手势保留。此处旧注「未实现切换逻辑」作废。
4. **媒体键**:**已落地(M2.81 起路由最近活跃媒体会话)**——播放/上下曲路由到最近活跃媒体会话(MSG_PLAYCTL),无会话时「抓住」不动作。此处旧注「路由待阶段 D」作废。
5. **插孔消抖(2026-09-01,真机日志实证)**:4.4/3.5 插拔的电气瞬态在音量键 ADC(jz_adc_aux,event2)上产生 VOL_UP 幽灵按住,launcher vol_ramp 曾从 24% 一路爬到上限 50(日志 225391 ramp 起 → 227213 爬满 → 紧随 audiod「jack changed」)。修:launcher 与 watchdog 音量键处理统一读 `/sys/class/switch/{headset,balance}/state`(节流读缓存:launcher 1s / watchdog 500ms,绝不在热路径每圈读文件),插孔状态变化后 **800ms 内忽略音量键边沿**(vol_ramp_begin 不起、在爬 ramp 中止、watchdog 单步忽略);另有 **ramp 总时长上限 VOL_RAMP_MAX_MS=3000** 兜底,防任何「持续按住」假象一次打满。~~SDK 输入层需同款消抖~~ → **SDK 侧已补齐(56c569f,meow_ui.a 12cdd5d7,hello/files/流媒体客户端重链热更)**:框架 App 前台时的音量键路径同款 800ms 消抖窗。
6. **音量反转统一(M2.95,2026-09-01)**:CS43198 音量寄存器 = **衰减量**(0=最响 255=静音),旧映射方向反(0 档炸耳、50 档最低)。launcher/audio.c + audiod + **watchdog `wd_vol_adj`** + SDK vol 四路统一 `dac = 255 - pct*255/100`。**watchdog 存盘修复(M2.93)**:`wd_vol_save` 旧 O_TRUNC 整文件重写 settings.conf 曾毁配置(整文件被抹/重复行/丢 max+step)→ 改读改写单键+去重(与 SDK 同款语义)。
7. **播放/暂停键(164) toggle(262,2026-09-01)**:SDK `meow_ui_media` 旧按本地 `g_last_state` 判 play/pause,流媒体客户端走自有 ipc_media 线程不经 SDK meta → 恒发 cmd=1 播放、播放中按键无效。修:164 **恒发 `MSG_PLAYCTL cmd=6`(toggle)**,由源侧按当前态翻转(launcher 透传不动结构;媒体卡片/NP 页按钮按 launcher 侧 META state 判,本就准,维持现状)。同批修:App 前台状态栏音量%/亮度实时刷新(launcher 叠加层 1s 节流 stat settings.conf,mtime 变才重读同步 g_sys)。
真机验收要点(§7):应用内电源单击/长按菜单/8s 强关、音量±调音量、播放/上下曲无反应(被抓住)、launcher 菜单同样一致、电源菜单任何界面可弹(含应用内)、息屏后任意键唤醒。