Files
MeowOS-For-R3P2/FRAMEWORK_DESIGN.md
T
MeowOS Dev 245bee2946 MeowOS for HiBy R3 Pro II — 公共发布版本(历史已重置)
• 全新单提交:清除含敏感信息的旧历史(sudo 口令、内网 IP、SSH 密钥路径、热点 SSID、设备 MAC)
• 本地开发文档/测试记录/构建脚本全部移入 gitignored 的 devdocs/ 与 scripts/build/(不入库)
• 保留:MeowOS 源码(launcher/watchdog/bootmenu/meow_svcd/SDK)、项目规范文档、mips-repo
增补组件:SDK 统一日志+通知 API、meow_svcd 服务管理器、mips-repo 软件仓库
2026-08-30 01:12:34 +08:00

224 lines
18 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 阶段 D:Activity / 通知 IPC 框架设计文档
> 状态:设计稿 v1(2026-08-28)。先出协议与架构,本阶段只设计、不实现。
> 前置: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 | ↓ | 下发通知清单(重同步) |
| 0x0030 | MSG_ACT_DECLARE | ↑ | (重)声明路由表 |
| 0x0031 | MSG_ACT_QUERY | ↑ | 解析 activity 链路 |
| 0x0032 | MSG_ACT_RESULT | ↓ | 返回链路 |
| 0x0040 | MSG_NAV | ↑ | 上报导航/请求退出 |
| 0x0041 | MSG_SHOW_ACTIVITY | ↓ | 令前端应用显示某屏 |
| 0x00F0 | MSG_SYS | ↓ | 系统事件(守护关闭/服务死亡/播放器状态) |
负载结构体见设计稿正文(m_hello/m_notify/m_register/m_act_* 等,定长多字节 LE)。
## 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 同一时刻单前台应用。
- 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 导航+前台会话改造**、**M4 后台服务保活**、**M5 通知中心 UI**、**M6 加固**:后续里程碑,本轮未做。
- ✅ **渲染地基(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`(客户端)。
---
## 附录 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)。其他播放类应用(如网易云)在后台播放时,通过接口提供**实时播放数据**(元数据、歌词、封面等),供启动器的播放界面显示;启动器界面也能向应用下发**播放控制指令**(播放/暂停/上一首/下一首/进度)。
**设计**(在 §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 */ 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 → 状态/音频子系统(已有,确认保留)。