Files
MeowOS-For-R3P2/FRAMEWORK_DESIGN.md
MeowOS 5aabede0cd feat(launcher): M4 后台服务保活+后台播放(FRAMEWORK_DESIGN §5/§9 落地)
- app.json 新字段 background/background_audio 解析入 struct app/meow_acct 注册表
- meow_ipc.h:MSG_REGISTER(m_register_t)/SERVICE_OK(m_ack_t.status=pid)/SERVICE_STOP/
  MSG_SYS(m_sys_t, SHUTDOWN=1/SVC_DEAD=2) 负载结构落地
- 新模块 meow_bgplay.c/h(自包含+ops 注入,仿 meow_media,宿主可单测):
  · 后台播放保活——声明 background_audio 且媒体会话 PLAYING 的 App nav-exit 不终止,
    进程+音频流保留;UI 冻结走 §10.5 /tmp/meow_notif_active SDK present 自抑(非字面
    SIGSTOP:冻结同进程播放线程断供 PCM,§10.5 真机实证);点图标/媒体卡片回前台=
    原进程恢复(chain/picker 忽略),停播后再退出=真退 SIGTERM
  · 无头后台服务——MSG_REGISTER spawn/stop/reap + 退避重启 1/2/4/10s cap +
    max_restart 熔断(清该 App 通知 + 注册连接广播 MSG_SYS{SVC_DEAD},重注册复位)
  · 卡拔例外(卡上二进制后台 App/服务仍 SIGTERM 防 SIGBUS)、崩溃照收、
    关机前 meow_bgplay_kill_all 有界回收(含 MSG_SYS{SHUTDOWN} 广播)
- util.c:MSG_REGISTER/MSG_SERVICE_STOP 分发(权限/声明校验链)+ ipc_conn_alive 连接
  存活查询 + meow_ipc_process 末尾挂 meow_bg_housekeep(drain/reap/退避 tick)
- app_launcher.c:launch_app_chain 入口 resume(bg_take 原进程回前台)+ nav-exit
  保活分支 + 转后台出口(杀看门狗/写自抑标记/复位顶条,跳过退出尾)+ 冷启动自动
  拉起静态 keepalive(mode=0) 服务(exec 路径约定=App 同目录 <svc> 文件)
- main_menu.c:应用列表「·后台」标注(宫格/列表,1s tick 按 change_seq 刷新)+
  两条退出尾 kill_all + unlink NOTIF_ACTIVE
- 宿主单测 test_bgplay.c 50 项全过(真 fork 子进程走状态机 + 假时钟退避熔断);
  test_media/test_notif_panel/test_notif_tf/test_vol_ramp_jack 回归全过;
  zig-mipsel-cc -Wall -Wextra 0 warning。launcher md5=c07d011c0769fca14d3bfb752d735463
2026-09-01 18:09:09 +08:00

351 lines
37 KiB
Markdown
Raw Permalink 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 阶段 D:Activity / 通知 IPC 框架设计文档
> 状态:协议/架构参考稿(2026-08-28 起草;**以下协议已随 M2.15-M2.96 各里程碑落地**,消息号以 `patch_v2/meow_launcherd/meow_ipc.h` 为准)。本阶段的「只设计、不实现」为起草期口径;M0-M3/M5/§10.5/媒体会话/amsd/meow_audiod(独占音频守护,规范 `devdocs/plan/AUDIOD_DESIGN.md`)已实现,**M4 后台服务保活+后台播放已落地(2026-09-01,见 §9 进度)**,M6 加固待排期。
> 前置:ANALYSIS.md §18(Launcher 全架构)、§11(播放器 unix socket 先例)、APPS.md、DEVELOPMENT_PLAN.md 阶段 0/D。
> 实现语言:启动器 C(musl 静态 MIPS32r2,zig-mipsel-cc);应用同为 C 静态 MIPS。
> 补充:本文件由 plan 子代理产出设计,主会话落盘,并附「后台运行/后台播放权限」(用户追加)。
## 0. 目标与一句话概括
让 MeowOS 成为"单机迷你 Activity 框架":
- 应用经 **AF_UNIX socket** 向主守护进程(meow_launcherd,即 MeowOS 核心)推送通知、注册后台服务;
- 通知绑定 target Activity;通知中心点击后按路由表解析启动链路,逐层拉起应用、压入按应用隔离的导航栈;
- 返回语义:应用内逐屏回退到"上一层",回到栈根才退出到应用列表(回到 MeowOS 主屏 / 播放器)。
**核心架构决策**:
1. **IPC 线程只读帧+解析+入队;所有状态变更由主循环单写者应用**——主循环对时序敏感(10ms 热键轮询、SIGSTOP 让位、fb pan),绝不在 socket IO 阻塞。
2. **导航栈:应用管屏内上翻,启动器管"回到根→退出到列表"边界** + 冷启动跳转的栈初始化。
3. **后台服务永远无头(不碰 fb0/输入)、永不被 SIGSTOP**——SIGSTOP 只用于抢占用 fb/输入的前台会话。
## 1. IPC 通道(AF_UNIX socket)
- 类型 `SOCK_STREAM`,路径 `/usr/data/meow_ipc.sock`(unlink 后 bind),`chmod 0666`,backlog 4。
- 帧格式:定长头(16B) + 变长负载,**全部小端 LE**(mipsel 原生)。
```c
struct ipc_hdr { /* LE */
uint32_t magic; /* 0x4D4F5701 = 'MEOW'|1 */
uint16_t version; /* 1 */
uint16_t type; /* msg_type */
uint32_t req_id; /* 请求id,响应回显 */
uint32_t len; /* payload 字节数 */
};
```
- `len` 上限 `MEOW_IPC_MAX=4096`;读满 16B 头→校验 magic/version→读 len→分发。
- 列表编码:`[u16 count]` + count 个 NUL 结尾字符串。
### 消息类型
| type | 名称 | 方向 | 用途 |
|---|---|---|---|
| 0x0001 | MSG_HELLO | ↑ | 声明 app_id/版本/能力 |
| 0x0002 | MSG_ACK | ↓ | 握手/应答 |
| 0x0003 | MSG_ERR | ↓ | 错误码 |
| 0x0010 | MSG_REGISTER | ↑ | 注册后台服务(保持连接) |
| 0x0011 | MSG_SERVICE_OK | ↓ | 服务登记成功 |
| 0x0012 | MSG_SERVICE_STOP | ↑ | 请求停止服务 |
| 0x0020 | MSG_NOTIFY | ↑ | 推送/更新通知 |
| 0x0021 | MSG_NOTIFY_ACK | ↓ | 落库结果 |
| 0x0022 | MSG_NOTIFY_DISMISS | ↑ | 撤下通知 |
| 0x0023 | MSG_NOTIFY_LIST | ↓ | 下发通知清单(重同步) |
| 0x0024 | MSG_NOTIFY_PROGRESS | ↑ | 实时更新通知进度(仅改内存活跃槽,不落盘) |
| 0x0025 | MSG_NOTIFY_QUERY | ↑ | 查询内存活跃通知集(MeowPanel 实时化前置) |
| 0x0026 | MSG_NOTIFY_DISMISS_ALL | ↑ | 一键清除(保留 ongoing/media/progress 进行中,同通知中心 UI) |
| 0x0027 | MSG_NOTIFY_QUERY_RESULT | ↓ | 活跃通知集序列化文本(JSON,字段同 TF 归档) |
| 0x0028 | MSG_NOTIF_OPEN | ↑ | **(已实现,号以 `meow_ipc.h` 为准)** App 检测到顶部下滑→请求 launcher 展开通知中心叠加会话(App 前台,见 §10.5) |
| 0x0029 | MSG_NOTIF_CLOSE | ↑ | **(已实现,可选用途)** App 告知结束/退出→launcher 收尾兜底(见 §10.5) |
| 0x0030 | MSG_ACT_DECLARE | ↑ | (重)声明路由表 |
| 0x0031 | MSG_ACT_QUERY | ↑ | 解析 activity 链路 |
| 0x0032 | MSG_ACT_RESULT | ↓ | 返回链路 |
| 0x0040 | MSG_NAV | ↑ | 上报导航/请求退出(**M3 导航栈已落地**) |
| 0x0041 | MSG_SHOW_ACTIVITY | ↓ | 令前端应用显示某屏 |
| 0x0070 | MSG_PICKER_CALL | ↑ | 请求跨 App picker 调用(发起方 A → 持有方 B;**已实现**,amsd 二期 agent-225:`am picker`/`picker-status`,files_app 注册 `pick_file`) |
| 0x0071 | MSG_PICKER_RESULT | ↓ | picker 返回值(候选结果回 A;**已实现**,amsd 二期) |
| 0x00A0 | MSG_AMS_START | → | amsd→launcher:请求拉起某 App(pkg + 可选 activity,含 picker 上下文 `MEOW_PICKER_*`;**已实现** agent-212/225) |
| 0x00A1 | MSG_AMS_KILL | → | amsd→launcher:请求终止某 App(SIGTERM 语义;**已实现**) |
| 0x0072 | MSG_META | ↑ | 媒体会话上报元数据/进度/状态(**附录 B 已落地**,最近活跃源回收) |
| 0x0073 | MSG_PLAYCTL | ↓ | 播放控制下发 / ↑ 控制器转发到最近活跃媒体会话(**已落地**) |
| 0x00F0 | MSG_SYS | ↓ | 系统事件(守护关闭/服务死亡/播放器状态) |
负载结构体见设计稿正文(m_hello/m_notify/m_register/m_act_* 等,定长多字节 LE)。消息号**一律以 `patch_v2/meow_launcherd/meow_ipc.h` 为准**,本节为引用性摘要。
## 2. Activity 路由表
- `app_id` = `MeowAPPs/<dir>/` 目录名(app.json 可覆盖)。
- `activity_id` 全局唯一为 `app_id/activity_id`。
- **启动链路**:根屏→目标屏的 activity_id 序列(`;` 分隔),链长=逻辑深度。
- 静态路由用 **app.json 扁平行**(不引入 JSON 解析器):
`route.<id>=path`(如 `route.nowplaying=home;search;nowplaying`);`framework=true`(看门狗返回发 SIGUSR1);`service.<svc>=mode:restart:max:window_ms`。
- 运行时 `MSG_ACT_DECLARE` 并集覆盖静态。
- 校验:`route` 缺失→深度 1 兜底;activity 未注册→ERR_UNKNOWN_ACTIVITY。
## 3. 导航栈
- `struct nav_stack`(每应用一个,≤16 深度),`active` 前台标记。v1 同一时刻单前台应用。**(M3 已落地,M2.80:`nav_stack` + `MSG_NAV` report/exit + `launch_activity` 链路注入 env `MEOW_ACTIVITY`/`MEOW_CHAIN`,栈根退出回主屏;通知点击按 `route_status`:0 拉起 / 1 NO ROUTE / 2 SOURCE NOT FOUND / -1 NONE 关面板不动作;裸 App 兼容。)**
- push/pop;**回退**:应用弹自己的屏并上报 `MSG_NAV{REPORT,depth,current}`;应用在根屏再按返回→`MSG_NAV{EXIT}`→启动器终止应用、恢复播放器、回列表。
- **冷启动通知跳转**:`resolve_chain` → 设栈深 → `launch_activity(app, chain)`,环境 `MEOW_ACTIVITY=<target>` + `MEOW_CHAIN=<id0>;<id1>;...;<top>`。
- 向下兼容:应用若不发 MSG_NAV,启动器保持初始深度;应用在根屏 `exit(0)` 即退出到列表(旧版行为)。
## 4. 通知生命周期
- 内存态(配额 ≤16/应用,满丢最旧);ttl 过期(1s 粒度);ONGOING 服务常驻通知(服务死→随清)。
- 点击按 route_status:0 跳转(tap_notification 逐层 launch);1/2 友好 toast(NO ROUTE / SOURCE NOT FOUND),不崩。
- 通知仅内存,不跨守护重启持久化(服务重启后重发重建)。
## 5. 后台服务保活
- `MSG_REGISTER` 登记;`service_spawn/stop/reap`;`SIGCHLD`→eventfd 回收;退避重启 1/2/4/10s(cap);`max_restart` 熔断→清通知+广播 MSG_SYS{2}。
- **服务无头契约**:禁止 open /dev/fb0、禁读 /dev/input/*、禁碰亮度/面板;**永不被 SIGSTOP**。
- SIGTERM 时依次关服务再 SIGCONT 播放器。
## 6. 与现有启动器整合
- `main()` 起 IPC 线程 + eventfd;主循环 `poll(eventfd,0)` 排空 pending。
- `run_menu` 的 poll 集合加 eventfd(通知徽标 + 阶段 B 下拉面板预留 API:`notify_count/at/dismiss`)。
- `launch_app` → `launch_activity(a, chain)` + env;waitpid 循环 poll eventfd 收 NAV{EXIT/REPORT}。
- 看门狗:framework 应用虚拟返回键发 SIGUSR1(沉浸手势同信号),非框架保持 SIGTERM。
- **所有 IPC/通知触发的 launch 必须走统一安全出口**(fb 备份→归 0→绘制→...→fb 恢复→SIGCONT),提前返回也要确保恢复。
## 7. 边界(不崩启动器,给友好提示)
未注册/路由缺失/二进制缺失/exec 失败/秒崩/服务熔断/配额/坏帧/应用死锁(看门狗强杀兜底)等,逐一对应 toast / MSG_ERR / 日志,见设计稿正文表。
## 8. 安全
单机信任模型,AF_UNIX 0666 无认证不防恶意;只做健壮性防御(帧长/配额/服务数/熔断/越界检查)。明确不做沙箱与恶意应用防护。
## 9. 实现里程碑
M0 IPC 骨架(含 meow_ipc 测试钩子)→ M1 路由表+解析 → M2 通知存储+分发 → M3 导航+前台会话改造+看门狗返回 → M4 后台服务保活 → M5 阶段 B 通知中心 UI 整合 → M6 加固+边界+稳定性验收。建议先落 M0+M1(纯内存/socket,SSH 全验证,不动播放器),再进 M3(触碰 SIGSTOP)。
### 进度(阶段 D)
- ✅ **M0 IPC 骨架**(0.7.10,M2.15):`meow_launcherd` 加 IPC 线程 + AF_UNIX `/usr/data/meow_ipc.sock`(unlink+bind+chmod0666+listen4)+ 帧解析(16B 头 magic=0x4D4F5701/version=1/type/req_id/len,LE)+ `MSG_HELLO/ACK/ERR` + eventfd 唤醒主循环 + 无锁 SPSC 内存环(`__sync`)+ 日志埋点。遵守 §1/§6.2:IPC 线程只读帧+解析+入队,主循环 `meow_ipc_process()` 单写者改状态,跨线程 eventfd,主循环 10ms 热键轮询每圈非阻塞排空(eventfd 失败时 10ms 轮询兜底)。测试钩子:`meow_ipc`(`patch_v2/meow_launcherd/meow_ipc.c`,静态 MIPS,与 evtool 同定位)+ launcher `--ipc-only N [--ipc-sock <path>]`。验证:`meow_ipc hello`→ACK、播放器不动(MeowOS 模式下无播放器即满足)。
- ✅ **M1 路由表 + 解析**(0.7.10,M2.15):`app.json` 扁平行 `route.<id>=path` / `framework=true` / `service.<svc>=mode:restart:max:window_ms` / `icon` 解析入 `g_accts` 注册表(主循环单写者);`MSG_ACT_DECLARE`(运行时并集覆盖静态)/`MSG_ACT_QUERY`/`MSG_ACT_RESULT`(深度+链路);`resolve_chain(app,activity)` 返回 `[root..target]` 链路与深度——`route` 缺失(app 未声明路由)→ 深度 1 兜底 `chain=activity`;声明了路由但 activity 非 route 键 → `MEOW_ERR_NOENT`(activity 未注册)。验证:`meow_ipc query <app> <activity>` 返回链路(qemu + 真机 MeowOS 模式均通)。
- ✅ **M2 通知存储+分发**、**M3 导航+前台会话改造+看门狗返回**、**M5 通知中心 UI 整合**(详见下,M2.65-M2.82 已落地);✅ **M4 后台服务保活**(2026-09-01 落地,见下);⬜ **M6 加固**:待排期。
- **M4 已落地(2026-09-01)**:`app.json` 新增 `background`/`background_audio` 解析入注册表(`struct app`/`meow_acct` 同名字段);`MSG_REGISTER`/`MSG_SERVICE_OK`/`MSG_SERVICE_STOP`/`MSG_SYS` 负载结构落地(`m_register_t`/`m_service_stop_t`/`m_sys_t`,MEOW_SYS_SHUTDOWN=1/SVC_DEAD=2);新模块 `meow_bgplay.c/h`(自包含+ops 注入,宿主可单测):**后台播放保活**——声明 `background_audio` 且媒体会话 PLAYING 的 App nav-exit 时**不终止**,进程+音频流保留(UI 冻结走 §10.5 `/tmp/meow_notif_active` SDK present 自抑,**非字面 SIGSTOP**:冻结同进程播放线程会断供 PCM,§10.5 真机实证),点图标/媒体卡片回前台=原进程恢复(chain/picker 忽略),停播后再退出=真退 SIGTERM;**无头后台服务**——MSG_REGISTER spawn/stop/reap + 退避重启 1/2/4/10s cap + `max_restart` 熔断(清该 App 通知 + 注册连接广播 MSG_SYS{SVC_DEAD},重注册复位熔断);卡拔例外(二进制在卡上的后台 App/服务仍 SIGTERM 防 SIGBUS)、崩溃照收、关机前 `meow_bgplay_kill_all` 有界回收(含 MSG_SYS{SHUTDOWN} 广播);主界面应用列表「·后台」标注(1s tick 按 change_seq 刷新);tick 挂载点=`meow_ipc_process` 末尾(主循环单写者排空点)。宿主单测 `test_bgplay.c` 50 项全过;amsd 侧 BG 状态展示=§6.3 顺延。
- **M3 已落地(M2.80,agent-202 · 85b4aea)**:`nav_stack`(≤16 深)+ `MSG_NAV` REPORT/EXIT + `launch_activity` 链路注入(env `MEOW_ACTIVITY`/`MEOW_CHAIN`)+ 栈根退出回主屏;通知点击按 `route_status`(0 拉起/1 NO ROUTE/2 SOURCE NOT FOUND/-1 NONE 关面板不动作);裸 App 兼容。
- **amsd(一期 agent-212 · 5fbf307 + 二期 agent-225)已落地**:活动管理器守护(svcd 托管 `trigger=boot`)+ `am` CLI(status/list/history/start/kill/`resolve`/`picker`)。二期将路由表迁 amsd(amsd 路由权威)+ **picker 契约**(`MSG_PICKER_CALL=0x70`/`MSG_PICKER_RESULT=0x71`,`am picker`/`picker-status`;files_app 注册 `picker.pick_file` 选文件返回路径)+ `MSG_AMS_START/KILL=0x00A0/0x00A1`(amsd→launcher 决策执行)。参见 `devdocs/plan/AMSD_DESIGN.md`。
- **M5 通知中心 UI 整合已落地(M2.65-M2.81)**:通知中心 + 媒体卡片 + Now Playing(媒体会话见附录 B,已落地:`meow_media.c` 最近活跃源、30s 超时回收、`MSG_META`/`MSG_PLAYCTL`)。
- **§10.5 App 前台唤起通知中心已落地(M2.82,agent-206 · 9b41957)**:`MSG_NOTIF_OPEN=0x28`/`CLOSE=0x29` + SDK `meow_ui_nav`/`meow_ui_media` 封装。
- ✅ **渲染地基(0.7.11,M2.16,前置基座)**:所有 UI 统一走 **RAM 离屏后备缓冲 `back_buf`(480×720×2=691,200B) + `meow_present`(dirty)** = `FBIO_WAITFORVSYNC` 等垂直同步 + 单次原子 memcpy(脏区或全帧)到 fb0(buffer0,yoffset=0)——无渐进/无中间态/无撕裂。脏区 `meow_dirty_add`(矩形合并集、相交吸 bbox、>12 转全屏、裁可视区);状态栏时钟/右侧格按需局部标脏。整合铺垫:框架后续 LAUNCH/NOTIFY/前台会话的绘制复用该机制(而非旧「全屏 clear→重绘到 buffer0」路径)。详情见 ANALYSIS.md §18.43。刷新率调度(display.refresh_rate 60/30/15 + refresh_always_max + 自适应降档 governor)归口 PERF_SCHEDULER.md。
- 测试钩子说明:`meow_launcherd --appinfo <app.json>`(打印单个 app.json 解析结果)、`--ipc-only N`(免 fb/输入跑 IPC)、`--ipc-sock <path>`(覆盖 socket 路径供 qemu sim);`meow_ipc hello|ping|query|declare`(客户端)。
---
## 10. 进程模型 / Supervisor 树 [源:2026-08-30 定案]
> 定位:本文档 §1-§9 聚焦「MeowAPP ↔ 启动器」的 Activity/通知 IPC;本节补齐**系统层面进程架构**——各系统进程的职责边界、监管关系与故障隔离,落实「一个崩不全部崩」。与 §5 后台服务保活**互补**:§5 管 MeowAPP 注册的**后台服务**,本节管 **MeowOS 自身系统进程**。跨文档:MEOW_APP_SDK §6.1、NOTIFICATION_SYSTEM §9、docs/MEOWOS_SPEC_REF §3.1/§5.1。
### 10.1 进程角色与 Supervisor 树
| 进程 | 职责 | 监管关系 | 崩溃隔离(核心诉求) |
|---|---|---|---|
| **meow_sysui**(新增,meow_svcd 托管) | **系统进程总监**:监管所有系统进程,监控存活 + 逐个拉起 | 监管 launcher / meow_svcd / meow_mdns / 未来媒体服务 / MeowPanel | 自身**最小依赖、不渲染、不承载重逻辑** → 最稳;**一个进程崩→只拉起它,绝不级联、绝不拖垮自身** |
| **meow_launcherd** | **系统 UI 渲染宿主**:SDK 全局状态栏、通知中心(下拉)、电源菜单、全局左缘返回/滑条;另含启动器主界面、设置页 | 被 sysui 监管;与 APP 进程独立 | 与 APP 渲染进程独立(见 §10.2) |
| **meow_svcd** | **服务管理器**:每个服务 = 独立子进程(fork+exec+setpgid) | 被 sysui 监管;其服务子进程由 svcd 托管 | 服务崩→svcd 捕获(waitpid)+只重启该子进程;**svcd 自身绝不因服务崩而崩**(信号/超时/僵死隔离) |
| **APP 进程** | 只渲染自己内容(经 SDK 语义事件) | 框架(IPC/launch)管理 | 崩→不连累 launcher / sysui / svcd |
**Supervisor 树(目标架构):**
```
meow_sysui(系统进程总监,meow_svcd 托管;最小依赖/不渲染/最稳)
├─ meow_launcherd 系统 UI 渲染宿主(主界面/设置页/电源菜单/全局状态栏/通知中心/全局手势)
├─ meow_svcd 服务管理器(服务=独立子进程;逐个子进程崩溃隔离)
│ ├─ meow_mdns mDNS 应答器(板载 /usr/data/meow/services.d/mdnsd.conf,trigger=boot)
│ ├─ meow_audiod 独占音频守护(M2.90;独占 hw:0,0+抢占+路由并入;HibyOS 模式门控 exit(0) 不启动——规范 devdocs/plan/AUDIOD_DESIGN.md)
│ └─ 未来媒体服务 / 其它 services.d 服务(TF MeowOS/services.d/…)
├─ 未来媒体服务 / MeowPanel(后置)
```
> **专项子服务(扩展,见 `devdocs/plan/SYSTEM_FRAMEWORK_SERVICES.md`)**:把**系统复用功能收敛到系统框架**,
> 新增两个 **svcd 托管、板载 `trigger=boot`** 的专项子服务挂在 svcd 之下——`meow_svc_perf`(性能/系统只读聚合)、
> `meow_svc_power`(关机/重启/升级/回HiBy 系统动作)。launcher 电源菜单与 MeowPanel 均改为**经这些服务 IPC 触发**,
> 不再直连 `sys_do_reboot`/爬 `/proc`。属 §10 supervisor 树的一种**既有托管模式的扩展**(服务仍为 svcd 子进程,
> 崩溃隔离/subreaper 语义不变,不改变本节定案;Ⅱ期补 .mpk 签名与关键 IPC 的 `os.meow.*` 鉴权)。电源 CLI 为
> `meow_svc_power <cmd>`(root 免鉴权、单一命令、不覆盖系统 shutdown/reboot),命令一览见 `docs/MEOWOS_SPEC_REF.md` §4。
> **launcher 源码拆分(M2.69 落地,纯代码组织重构,不影响本 §10 进程模型)**:`patch_v2/meow_launcherd/meow_launcherd.c`
> (曾 9778 行单文件)拆为 `patch_v2/meow_launcherd/` 多模块(14 模块
> `main_menu/statusbar/settings_page/power_menu/notif_center/app_launcher/fb_compositor/audio/backlight/net/about/font_theme/keys/util`
> + 共享头 `meow_launcher_internal.h`;`build_launcher.sh` 列模块)。二进制名 `/usr/bin/meow_launcherd`(bootmenu `LAUNCHER_BIN`)
> 不变、行为不变(见 README §2.3)。
> **托管关系澄清**:定案中的「meow_sysui(新增,meow_svcd 托管)」指 sysui 由**开机启动链**拉起(现网 S89 init.d/S90 bootmenu 归属,后续归 sysui 自身),并居于 svcd **之上**为总监——**不是** svcd 的子进程。监管方向固定:**sysui 总监 → svcd 被监管 → 服务为 svcd 子进程**。即便将来引导顺序先起 svcd 再起 sysui,此方向不变。
**监管语义(权威)**:
- **一个崩、只拉起它**:任一被监管进程崩溃(非零退出/被信号杀)→ 所属 supervisor **只重启该进程**,不级联重启、不影响相邻进程、不拖垮 supervisor 自身。
- **svcd 崩 → sysui 拉起**;launcher 崩 → sysui 拉起;mdns 崩 → svcd 拉起(或 sysui 兜底)。
- **「一个崩不全部崩」= 每进程独立 + 总监逐个拉起 + 单项故障不扩散**;「服务崩溃不导致 meow_svcd 崩溃」= **服务全部子进程化**(fork+exec+setpgid,svcd 只 waitpid 感知,绝不 dlopen/共享内存接服务)。
**现网 vs 定案(迁移说明,避免矛盾)**:
- 现网:launcher 由 bootmenu `execv` 起动(S90meow_bootmenu);svcd 由固件 `etc/init.d/S89meow_svcd` 自启(`-f` 前台)。二者**当前互不监管**。
- 定案:改为 **meow_sysui 统一监管** launcher/svcd/mdns/媒体服务/MeowPanel。属**系统基建线**(渐进迁移,非一次性推翻现网 S89/S90)。在此落地前,现网的「bootmenu+init.d 各自拉起」仍有效,但**不得**新增依赖打破「进程独立 + 崩溃隔离」约束。
- **已落地(M2.83)**:launcher 的启动权已由 bootmenu 移交 sysui(`S70meow_sysui` 预置 `sysui.d/launcher.conf` `enabled=1`;bootmenu 在 MeowOS 模式让位——sysui 在则不 exec launcher,只由 sysui 拉起/重启;sysui 不在时 bootmenu 兜底 exec)。svcd 由 sysui 监管(`svcd.conf` `enabled=1`,S89 在 sysui 存在时交给 sysui)。**仍待迁移**:mdns(svcd 负责,sysui 兜底默认关)、未来媒体服务、MeowPanel。
### 10.2 系统 UI 归属与进程隔离 [源:2026-08-30]
- **系统组件渲染归系统进程(launcher)**:状态栏 / 通知中心(下拉)/ 电源菜单 / 全局左缘返回与滑条等**全局叠加层**,一律由系统进程(meow_launcherd)负责渲染;**APP 进程不渲染系统 UI**(跨引用 MEOW_APP_SDK §6.1 ③「系统级控件仅系统内部」)。
- **SDK 提供系统组件 API 仅供系统进程链接调用**:SDK 内保留系统级控件的内部接口位(§6.1 ③);**用户 App 拿不到**、**不可自建悬浮层/全局叠加**(会引入遮挡、冲突、性能与安全风险)。App 这类需求只能走 SDK 标准能力。
- **进程隔离**:SDK 负责**系统组件渲染**的进程(launcher)与负责 **APP 渲染**的进程**相互独立**——APP 卡死/崩溃时,系统 UI(launcher)**不崩**,始终可息屏/返回/下拉通知中心(对应「物理键全局接管,APP 禁映射」APPS §3.4.1)。
- **APP 侧职责**:只画自己的内容;经 IPC 上报**全屏声明**(`fullscreen`/`route.<id>.fullscreen`)、**内容区域**(inset)与**前台 activity**;系统 UI 据此做叠画(复用 fb 双缓冲 `fb_backup/restore/pan`)与 hits 命中分流(MEOW_APP_SDK §6.1 交互分层:③ 系统全局 → ② App 全局 → ① 当前 Activity 页面控件)。
- **「同一个状态栏」正确闭环([源:2026-08-30] 收敛修正,M2.66)**:状态栏是**同一个渲染主体**,不是「样式一样的两套实现」——
- **系统进程(launcher)统一渲染**:无论主界面还是 App 前台,状态栏都由系统 UI 进程(meow_launcherd)渲染——主界面与 App 前台用**同一个**状态栏实例(真实同一主体,非各画各的)。
- **App 前台 → 状态栏为系统叠加层**:App 前台时状态栏作为**系统叠加层**盖在 App 内容之上,复用 fb 双缓冲叠加(`fb_backup/restore/pan`,见 §10.5 / `devdocs/plan/NOTIF_CENTER_APP_OVERLAY_PLAN.md`);与通知中心/电源菜单区别:状态栏**常驻**(仅顶条 28px,不进/不出会话、非模态面板)。
- **App 进程不渲染状态栏**:SDK 全局状态栏**仅系统进程链接渲染**;**App 进程不自绘、拿不到**(§6.1 ③ 系统级控件仅内部;App 这类需求只能走 SDK 标准能力,不得自建全局叠加/悬浮层)。
- **数据源唯一**:状态栏数据(时间/电量/WiFi/音量/亮度)由 launcher **统一喂/取**(单一权威源)→ 主界面与 App 两边显示**必然一致**(根治 M2.66「launcher 右侧有亮度、App 没有」的不一致)。
- **与 §10 定案闭环**:§10.1 表已定「meow_launcherd = 系统 UI 渲染宿主」;本节把状态栏明确纳入该系统 UI 渲染宿主职责,与「APP 不渲染系统 UI」(§10.2 首条)自洽,落实「一个渲染主体 + 一个数据源」。
### 10.3 通知中心归属 [源:2026-08-30]
- **通知中心 UI 渲染主体 = 系统进程(launcher),非 APP**(跨引用 NOTIFICATION_SYSTEM §9)。
- **数据**:通知列表经 IPC 从通知存储/通知服务读(`MSG_NOTIFY_LIST` 重同步等),launcher 只做 UI 呈现与手势。
- **交互**:状态栏下滑展开、上滑/点面板外关、左缘返回关(与全局左缘返回/顶部滑条按起始位置分流,见 docs/MEOWOS_SPEC_REF §5.1)。
- **协议/约束**:遵守 freedesktop 字段、配额(每 App 4 类型×每类型 4、媒体单例)、TTL、转储(10s+10MB ring)、urgency/icon/progress(见 NOTIFICATION_SYSTEM §5-§8)。
### 10.4 启动器 SDK 改造 [源:2026-08-30]
- **状态栏收敛为单一 SDK 全局**:launcher 现状私有 `draw_statusbar()` **退役移除**,统一走 SDK 全局状态栏(`meow_ui.h` §3.1;28px,默认显示,APP 声明全屏/`fullscreen` 才隐藏/收合)。
- **launcher 主界面 / 设置页 / 电源菜单全部迁到 SDK 控件**:逻辑/渲染走 SDK(MEOW_APP_SDK §6.1 ② App 跨 Activity 控件、§5.4 A① 分组设置表单、§5.7 B④ 面板等模板),MD3 化、日/夜主题(`display.theme_mode`)、全局 UI 统一。
- **不让 app 自建叠加**:app 一律经 SDK 标准能力;系统级叠加(状态栏/通知中心/电源菜单/全局手势)只在系统进程内实现。迁移后 launcher 与 APP 用同一套 SDK 渲染地基,观感/生命周期统一。
### 10.5 App 前台划出通知中心(跨进程叠加会话)[源:2026-08-30]
> 定位:补齐「全屏 App(如 hello)前台时,App 进程内顶部下滑也能唤起**由 launcher 渲染**的通知中心」。
> 详细实现方案见 `devdocs/plan/NOTIF_CENTER_APP_OVERLAY_PLAN.md`;本节为**定案决策**(归属/归属不变/协议/会话/故障隔离)。
- **交互与归属(不变)**:App 前台时顶部下滑,**App 进程只负责「检测手势 + 经 IPC 上报」**;通知中心
**仍由 launcher 渲染**(符合 §10.2「系统 UI 归 launcher」/`MEOW_APP_SDK §6.1 ③`/`NOTIFICATION_SYSTEM §9`);
**App 进程不渲染系统 UI**(不叠加状态栏/通知中心)。手势检测在 App 进程 SDK(`meow_ui_input.c` 已把
「起点在顶部热区+向下主导」识别为系统保留手势 `MEOW_EV_NOTIF_PULL` → 路由 `meow_ui_sys_notif_pull()`)。
- **跨进程握手(复用现有 IPC,不新增 socket)**:复用 `AF_UNIX /usr/data/meow_ipc.sock`(`meow_ipc.h
MEOW_IPC_PATH`,launcher `ipc_thread` bind/listen)。拟新增上行消息:
- `MSG_NOTIF_OPEN`(App→launcher):App 检测到顶部下滑→请求展开通知中心叠加会话;负载 `m_notif_open_t`
(app_id/event_seq/origin_x/origin_y/hotzone/flags)。launcher 回 `MSG_ACK` 受理(best-effort,App 不强依赖)。
- `MSG_NOTIF_CLOSE`(App→launcher,可选用途):App 告知结束/退出→launcher 收尾(清 active/SIGCONT 兜底)。
- 号段/结构以 `meow_ipc.h` 回填为准。**已实现(M2.82,agent-206 · 9b41957)**:`MSG_NOTIF_OPEN=0x0028` / `MSG_NOTIF_CLOSE=0x0029`(`0x0025/0x0026` 已被通知查询/清除 IPC 占用);SDK 侧 `meow_ui_nav`/`meow_ui_media` 封装同步落地,顶部下滑手势→IPC、launcher SIGSTOP→读帧→叠加→接管输入→SIGCONT(面板内 App 崩溃即关)。
- **launcher 叠加会话(复用电源菜单对 App 的冻结模板)**:收到 `MSG_NOTIF_OPEN`(且当前在 App 前台会话,
`launch_app` waitpid 循环内)→ **SIGSTOP App** → 读回 App 帧(`memcpy` fb0 buffer0 → back_buf,App 帧恒
buffer0 不走 `fb_backup_player`;同 `pm_capture_app_frame`)→ 写 `/tmp/meow_notif_active`(同
`/tmp/meow_power_menu_active`,让 watchdog 让位)→ 叠加渲染 `draw_notif_center` + `meow_ui_flush` →
**接管输入**(`open(DEV_TOUCH)`+`kp_open`,App 已冻不影响)→ 关闭(上滑/点空白/左缘左滑/点通知/物理键)→
恢复 App 帧 → `unlink(active)` → **SIGCONT App** → 重播输入基线。差异:背景=App 帧(非应用列表);
关闭后回 App(非回 run_menu)。
- **App 崩溃/卡死**:launcher 会话子循环周期用 `waitpid(pid,&st,WNOHANG)`/`kill(pid,0)` 探测;App 死→立即结束会话
(不 SIGCONT 死进程、不恢复死帧),走既有**统一应用退出路径**归位;launcher 不崩(`kill(pid,0)` 存活检测
与 watchdog 让位语义同 `util.c`(IPC 服务端 `ipc_thread`/`ipc_dispatch`)。
- **全屏/沉浸不冲突**:全屏/收合时 SDK 顶部热区缩小为 `MEOW_SBAR_HOTZONE_FS=4`(或提示线高),**仍保留顶部
一处下拉入口**(`meow_ui_statusbar_hotzone()`),spec-ref §3.1/A-13/§5.1 已定「全屏下顶部下滑仍开通知中心」。
- **与 M3 关系**:本方案是 M3「前台会话」的一个切面(App 前台会话+跨进程叠加)。**本方案先行**(握手+叠加会话+
故障隔离,不依赖 M3);通知点击 `target_activity` 的 activity 级跳转 / 点击通知**跨 app 启动** / nav_stack 回退
**留 M3**(首期:点通知 = dismiss + 关面板 + SIGCONT 回当前 App)。
---
## 附录 A(用户追加):后台运行 / 后台播放权限
**需求**:允许应用声明后台运行、后台播放等能力,避免播放类应用切到后台被直接终止。hiby 播放器作为系统应用单独适配。
**设计**:
- 应用经 `MSG_HELLO`/`MSG_REGISTER` 声明 **声明式权限**:`PERF_BACKGROUND`(可后台常驻)、`PERF_AUDIO_BACKGROUND`(后台音频/播放,要求系统**不因前台切换而杀掉**)。
- 权限粒度在 `MSG_HELLO.flags`/`MSG_REGISTER.flags` 扩展位:`MF_BACKGROUND`、`MF_PLAYBACK`。
- **后台播放的保活路径**:真正后台播放音源 = 注册**后台服务**(§5)+ 绑定一条 ONGOING 通知(用户可见"正在播放")+ 声明 `PERF_AUDIO_BACKGROUND`。守护进程据此**不因前台应用切换杀掉它**;退出前台会话时若该应用声明了后台能力,只结束其前台会话(SIGSTOP 播放器释放 fb/输入),**保留服务进程与音频**。
- **hiby 播放器单独适配**:作为 `app_id=hiby` 的内置系统应用(阶段 0),MeowOS 管理其启停。它天然是"后台播放"——MeowOS 主屏/通知中心使用时,hiby 播放器作为后台服务/音频源继续播放(符合其"音乐播放器"角色,不因用户切到 MeowOS 界面而停歌)。实现上:hiby 播放器注册为系统级后台音频,MeowOS 在任何前台会话下都不 SIGSTOP/终止它,仅在其自身退出时回收。
- **前台/后台切换规则**(框架统一):
- 前台应用(占用 fb/输入)切后台 → 结束其前台会话(恢复 fb/播放器),除非其声明 `MF_PLAYBACK` 且音频在播——此时仅释放视图,音频服务保留。
- 后台服务从不被 SIGSTOP;只有前台会话才 SIGSTOP。
- 缺省(未声明)应用:切后台即终止(现行为),最保守。
- **注意**:真正"切后台还在放"仍受硬件约束——音频只能走 hiby 播放器 socket 代播(44.1k/16bit)或应用直开 hw(需先确认 SIGSTOP 后播放器是否释放声卡,阶段 E 实测)。框架只保证生命周期(不被杀),不保证声卡空出;声卡占用问题是独立事项,记录为阶段 E 待测。
(完)
---
## 附录 B(用户追加):默认播放控制界面 / 正在播放(Media Session)
**需求**:MeowOS 启动器内置一个**默认播放控制界面**(Now Playing)。其他播放类应用(如流媒体客户端 dev.player.ncm)在后台播放时,通过接口提供**实时播放数据**(元数据、歌词、封面等),供启动器的播放界面显示;启动器界面也能向应用下发**播放控制指令**(播放/暂停/上一首/下一首/进度)。
**设计**(在 §1 IPC 基础上新增"媒体会话"消息):
- **上报(应用→启动器)`MSG_META`**:实时元数据。负载:
```c
struct m_meta {
char title[128];
char artist[128];
char album[128];
uint32_t pos_ms; /* 当前播放位置 */
uint32_t dur_ms; /* 总时长 */
uint32_t state; /* 0=停止 1=播放 2=暂停 3=缓冲 */
uint32_t flags; /* MF_ART / MF_LYRIC / MF_COVER */
char artwork[192]; /* 封面: 本地路径或 MeowOS 存储槽位 */
char lyric[192]; /* 歌词: 路径或文本槽位 */
char app_id[32];
};
```
- 流式更新(播放位置/进度)用高频 `MSG_META`(或拆出轻量 `MSG_PROGRESS`,由应用按 ~1s 推送);元数据变化低频。
- **指令(启动器→应用)`MSG_PLAYCTL`**:
```c
struct m_playctl { uint32_t cmd; /* 1=播放 2=暂停 3=上一首 4=下一首 5=seek 6=播放/暂停toggle(物理键164恒发6,由源侧按当前态翻转;262) */ int64_t seek_ms; };
```
- 启动器播放界面上的按钮/滑条 → 通过该应用的**服务连接**下发。
- **注册**:播放应用声明 `MF_PLAYBACK` 并注册**媒体会话**(`MSG_REGISTER` 带 `svc=media_session` 或 `HELLO.flags` 含 PLAYBACK)→ 成为当前"正在播放"提供的源。
- **启动器表现**:
- 播放界面在**主屏/通知中心**有入口(默认一个 Now Playing 卡片):封面(缩略图,从 artwork 路径/槽位读)、标题/歌手/专辑、进度条、播放/暂停/上下首按钮。
- 歌词/封面若应用提供(MF_LYRIC/MF_COVER),启动器可显示(滚动歌词、封面大图)。
- 无音频源时显示"未在播放"占位。
- **hiby 播放器适配**:`app_id=hiby` 作为系统应用上报元数据(其自带曲目信息),启动器播放界面可显示官方播放器的歌名/进度,并下发放置控制。实现时从 hiby 播放器读元数据(其 SQLite 库 / 运行时状态)或后续再经其 socket 对接;阶段 0/D 落地后作为系统应用接入。
- **边界**:无应用上报 → 播放界面空态;多源 → 以最近活跃媒体会话为准(可扩展为"媒体源选择");应用退出/服务死亡 → 清 Now Playing 并回空态;进度/歌词缺省则相应区域留空。
- **与后台播放权限的关系**:MF_PLAYBACK 声明 + 媒体会话上报 → 框架视为后台播放源;启动器在主屏/通知中心时**不因用户离开该应用前台而停其音频**(附录 A),保证"切到 MeowOS 界面歌还在播、界面还能显示和控制"。
(完)
---
## 附录 C(用户追加):通知接口适配 freedesktop.org 桌面通知规范
**需求**:为最大化兼容既有通知生态,通知中心接口适配常见 X11 桌面应用使用的接口规范。
**决定**:通知后端提供**双接口**——
1. **轻量 IPC**(本框架 §1 的 AF_UNIX,MeowAPPs 用,带 Activity 路由等定制特性)。
2. **`org.freedesktop.Notifications`(freedesktop.org Desktop Notifications 规范)**——设备已跑 dbus-daemon 系统总线 + glib/gio/libdbus 可用,新增独立守护 `meow_notify_dbus` 把该 D-Bus 接口桥接到 MeowOS 通知中心后端。
**`org.freedesktop.Notifications` 方法/信号**(标准):
- `Notify(app_name, replaces_id, app_icon, summary, body, actions[], hints{}, expire_timeout)` → 存入通知后端(映射 summary/body/app_name/icon + 可选 target Activity via hints)
- `GetCapabilities()` / `GetServerInformation()` / `CloseNotification(id)` / `GetCapabilities`
- 信号:`NotificationClosed(id, reason)`、`ActionInvoked(id, action_key)`
**实现要点**:
- `meow_notify_dbus`(独立小守护,链 libdbus/GDBus)在系统总线注册 `org.freedesktop.Notifications`;收到 Notify → 经 MeowOS IPC 后端入通知存储;后端关闭/动作 → 回发信号。
- 任意遵循该规范或用 libnotify 的客户端(含未来移植的 X11/桌面应用)→ D-Bus 推送 → MeowOS 通知中心显示。
- MeowAPPs 可继续用轻量 IPC;第三方兼容走 D-Bus。
- 阶段 D 实现里把本兼容层并进(M4 附近),通知中心(阶段 B)消费统一存储。
---
## 附录 D(用户定案):与成熟标准统一(全部采纳)
> 最大化生态兼容;阶段 D(及媒体会话/设置/应用规范)实现时一并落地。
### D1. MPRIS(机制:`org.mpris.MediaPlayer2`)
- 对齐媒体会话(附录 B):MeowAPPs 播放器暴露 **`org.mpris.MediaPlayer2` / `.Player`** D-Bus 接口(设备已有 `mpris-proxy`);MeowOS Now Playing(默认播放控制界面)经 MPRIS 读取元数据/进度/封面 + 下发播放/暂停/上下首/seek。
- 方法/属性:`Play/Pause/Next/Previous/Stop/PlayPause`、`Seek/SetPosition`、`Metadata`(title/artist/album/artUrl/length)、`PlaybackStatus`、`Position`;信号 `Seeked`/`PropertiesChanged`。
- MeowOS 通知中心/媒体卡片显示 MPRIS 源;多个源时按最近活跃选择。
### D2. XDG Base Directory(数据目录兼容)
- 启动应用时,在注入 `MEOW_DATA_DIR`/`MEOW_CACHE_DIR` 基础上,**同时设置**:
- `XDG_DATA_HOME=<MeowData/<pkg>/data>`、`XDG_CACHE_HOME=<MeowData/<pkg>/cache>`、`XDG_CONFIG_HOME=<MeowData/<pkg>/config>`(config 目录首次启动若缺则建)。
- 遵循 XDG 的移植应用直接复用我们数据目录,零改码。
### D3. freedesktop Desktop Entry(应用元数据对齐)
- `app.json` 字段与 `.desktop` 对齐:`Name`/`Icon`/`Exec`/`Categories`/`Comment`/`StartupNotify`;可额外映射 `org.freedesktop` 相关。
- 图标可选遵循 freedesktop 图标主题(hicolor 等);MeowOS 应用列表读取这些元数据。
### D4. UPower / sysfs(电源标准,天然兼容)
- 已读 `/sys/class/power_supply`(电量/充电/电压),对齐 UPower 语义;MeowPanel/状态栏用同名概念。保留。
### D5. syslog 日志输出(可选)
- MeowOS 日志除 TF 卡/内存环外,**追加输出到 syslog**(设备 busybox syslog;`log.level` 控制),让 MeowOS 关键日志进标准系统日志流,便于与系统日志合并排查。
### D6. ALSA mixer 控制命名(音频兼容)
- 音量已对齐 CS43198 标准 control(`numid=1 Left Playback Volume`/`numid=2 Right Playback Volume`),MeowOS 音量键/面板用同名字节,与 ALSA 生态一致。保留。
## 实现归入
- D1/D2/D3 → 阶段 D 媒体会话/应用规范/应用启动(FRAMEWORK_DESIGN §1-§6 扩展)。
- D5 → 日志系统升级(SYSTEM_SETTINGS log.*)。
- D4/D6 → 状态/音频子系统(已有,确认保留)。