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

11 KiB
Raw Blame History

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 菜单同样一致、电源菜单任何界面可弹(含应用内)、息屏后任意键唤醒。