chore(sdk): 公开仓适配 — 剔除构建产物/宿主测试二进制; vendored meow_font.c/meow_ipc.h/meow_font.h/meow_notif.h 使其自包含; build_sdk.sh/build_hello.sh 改 MEOW_CC/MEOW_SYSROOT 可配置; 去除内部路径与 ncm 引用

This commit is contained in:
MeowOS committed 2026-09-01 21:12:17 +08:00
1 parent 4f66da66ad
commit 86605d01e3
26 files changed
+1938 -32

No files matched your search

+174
View File
@@ -0,0 +1,174 @@
#ifndef MEOW_FONT_H
#define MEOW_FONT_H
/*
* meow_font.h — MeowOS 预渲染位图字体运行时(独立、可复用,不绑定启动器)。
*
* 数据来源:由 gen/gen_font.py 生成的 font.png(灰度 PNG,bit depth 4|8,含各字号面)
* + font.idx(索引:头部 + 每面元数据 + 每字符 16B 记录)。
*
* 设备端加载:模块内建最小 PNG 解码(仅支持灰度非隔行)经 zlib inflate + 反滤波还原像素,
* 无需 libpng;交叉链接 musl 静态 libz.a。像素面按 depth=4|8 打包存储,取像素时按 nibble 解包。
*
* 绘制模型:drawtext(fb, x, y, utf8, color, size);(x,y)=行首「升线(top)」锚点;
* baseline = y + ascent;每字形 blit 于 (x + pen + dx, y + dy);pen 累加 advance。
* color 为 565 位 RGB(R 在 bit15..11,G bit10..5,B bit4..0),与 launcher 一致。
* 无字回退:缺码位画空心方块(tofu)并前进空格宽度。
*
* 字号:字库含若干原生面(如 28、20)。drawtext 请求 size 时先找精确匹配面;
* 若无则就近取一面做最近邻缩放(最优仍用原生字号)。
*/
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* 设置 framebuffer 几何:宽/高(像素)与每行字节数(如 480*2)。绘制前调用一次。 */
void meow_font_set_fb(unsigned fb_w, unsigned fb_h, unsigned pitch_bytes);
/* 加载字库(全部字号)。成功返回 0,失败返回负值。可重复调用(先卸载旧的)。 */
int meow_font_load(const char *png_path, const char *idx_path);
/* 释放字库。 */
void meow_font_unload(void);
/* 按档装载大字库(字体档位分层,见 MEOWOS_SPEC_REF §5.2/§5.7.8 与 meow_ui.h §10):
* tier = 0 common≈4k(小/默认)/ 1 gbk≈20k+(大字库)/ 2 full(全,可选)。
* png/idx 为调用方已按档解析的设备绝对路径(launcher 经 env 注入)。切换时先 unload 旧
* 再 load 新(释放旧 atlas —— 大字库 GBK 解码约 5-15MB,避免新旧同时驻留内存)。
* 返回 0 成功,负值失败(失败时旧库已释放,调用方应回退卡默认/固件)。
* 由 meow_ui_gfx.c 的 meow_font_set_tier() 在档位变化时唤起;meow_font_load() 仍是装载
* 系统默认(slot0)字库的入口。 */
int meow_font_reload_tier(int tier, const char *png, const char *idx);
/* 某字号是否存在(命中原生面返回 1)。 */
int meow_font_has_size(int size);
/* UTF-8 字符串渲染宽度(px)。字面不存在返回 0。 */
int meow_font_width_text(const char *utf8, int size);
/* 行高(px = ascent + descent)。 */
int meow_font_line_height(int size);
int meow_font_ascent(int size);
/* 绘制文本:(x,y)=行首升线顶部;color=RGB565。已按 fb_w/fb_h 裁剪。 */
void meow_font_drawtext(uint16_t *fb, int x, int y, const char *utf8,
uint16_t color, int size);
/* 描边绘制:先以 outline_color 将每字形向 4/8 邻域平移 ol 绘制一圈,再以 color 填充。 */
void meow_font_drawtext_outline(uint16_t *fb, int x, int y, const char *utf8,
uint16_t color, uint16_t outline_color, int ol, int size);
/* ---- 字符分类器(multi_font 逐字符路由的依据;按 codepoint 归类)---- */
typedef enum {
MEOW_FCLS_CJK = 0, /* CJK 表意文字 + 扩展 / 兼容表意(U+3400-4DBF/4E00-9FFF/20000-2FA1F/…) */
MEOW_FCLS_CJK_SYM = 1, /* 全角/中文标点(U+3000-303F、U+FF00-FFEF、U+2014/2018-201D/2026、U+00B7) */
MEOW_FCLS_NUM = 2, /* 0-9 */
MEOW_FCLS_LATIN = 3, /* A-Za-z(基本拉丁字母) */
MEOW_FCLS_LATIN_SYM = 4, /* 半角标点(ASCII 非字母数字:空格/括号/引号/运算符/控制符) */
MEOW_FCLS_OTHER = 5, /* 其他(假名/韩文/他文字/扩展区等) */
MEOW_FCLS_COUNT = 6
} meow_fclass;
/* 把一个 codepoint 归类为上述之一。 */
int meow_font_class_of(uint32_t cp);
/* 校验码位是否在「将用于渲染它的字库」中存在字形(1=有,0=缺字/字库未加载→渲染为豆腐)。
* multi_font 开启时按分类路由到对应字库,关闭时仅查全局字库(slot 0)。 */
int meow_font_has_glyph(uint32_t cp);
/* ---- 多字体(MEOW_FCLS* 逐字符路由)----
* 槽位模型:slot 0 = meow_font_load() 装载的全局/默认字库(font.file);额外字库经
* meow_font_load_slot() 装载后,用 meow_font_set_class_slot() 把某字符类指到某一槽。
* meow_font_drawtext/width_text/line_height/... 在 meow_font_enable_multifont(1) 开启时
* 逐字符分类 → 用该类别对应槽的字库取字形与度量;缺该类别字库/未加载 → 回退 slot 0。
* 关闭(默认)时一律走 slot 0,行为与单字体完全一致(零额外开销)。
* 同 family 去重、类别字库 ≤3 套上限 + 打包面内存预算由 meow_font_config_multifont() 统一处理(launcher 与 SDK 共用)。 */
#define MEOW_MAX_SLOTS 4 /* slot0(全局) + ≤3 套类别字库。真机 56MB:多字体每套字库都驻留整幅
* 打包面(common≈4.2MiB / gbk≈16.6MiB),5 套太多会叠加 OOM;故硬上限
* 收到 4,且 meow_font_config_multifont 另按 meow_font.c 内
* MEOW_MULTIFONT_MEM_BUDGET 做「总打包面字节」预算(超出→新增类别回退全局)。 */
int meow_font_load_slot(int slot, const char *png_path, const char *idx_path); /* 0=成功,负值失败 */
void meow_font_unload_slot(int slot);
void meow_font_enable_multifont(int on); /* 0=单字体(默认);1=逐字符分类路由 */
void meow_font_set_class_slot(meow_fclass cls, int slot); /* slot 越界/载入失败 → 该类别回退 slot 0 */
/* 一个字符类的候选字库路径(绝对路径,已由调用方按卡根解析;png=NULL/空 = 跟随全局)。 */
typedef struct {
const char *png;
const char *idx;
} meow_font_class_cfg;
/* 依据开关 + 各类候选配置多字体:同 png 路径去重(含与全局相同 → 直接用 slot 0),
* 独立字库数(含全局)> MEOW_MAX_SLOTS 时截断并置 *truncated=1(此前已装载的保留)。
* 返回 0 成功,负值失败;*distinct = 实际装载的不同字库数(含全局)。 */
int meow_font_config_multifont(int on,
const char *global_png, const char *global_idx,
const meow_font_class_cfg cfg[MEOW_FCLS_COUNT],
int *distinct, int *truncated);
/* ---- MeowPanel 预留:TF 卡字体库 .zip 导入/导出(TODO,未实现)----
* 当前仅声明占位,供 MeowPanel 后续接入;不实现、不接 zip 库。
* 调用方约定(待实现):导入=校验 .zip 内含 font.png+font.idx+font.json 三件套,
* 校验通过后解压到 TF 卡 MeowOS/fonts/<family>/<weight>/(family/weight 取自 font.json 的
* family/weight 或 zip 名,缺省 weight=regular;冲突时覆盖需先确认);导出=把
* MeowOS/fonts/<family>/<weight>/ 三件套打包为 <out_zip>。
* 目录布局与 font.json schema 见 docs/MEOWOS_SPEC_REF.md §1.2/§5.2。
* 返回码:MEOW_OK=0 成功,负值错误码(沿用本模块失败负值约定)。 */
int meow_font_import_zip(const char *zip_path); /* TODO:MeowPanel */
int meow_font_export_zip(const char *family, const char *out_zip); /* TODO:MeowPanel */
/* ================================================================== */
/* M2.58 字体索引 + 应用字库查询(规格 §5.7:索引文件 / 查列表 / 丢失降级默认) */
/* ================================================================== */
/* 系统字体列表的持久化快照 = TF 卡 <card_root>/MeowOS/config/fonts/index(CSV,每套一条:
* "family","weight","path","label","tier",glyph_count
* path = 卡根相对 font.png(如 MeowOS/fonts/misans/regular/font.png)
* label = 显示名(含字重 + 尺寸标记,如 `MiSans Regular(common≈4k)`)
* tier = common|gbk|full(档位,信息用 + 驱动按需加载)
* launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后写该文件(覆盖,含默认行 index0);
* SDK 侧 meow_font_get_available_count()/enumerate() 只从这个文件读,不依赖 launcher 内存数组;
* 无卡/无 index → 仅 1 项板载默认(family=default)。 */
#define MEOW_FONT_INDEX_REL "MeowOS/config/fonts/index"
/* 权威列表数据模型(SDK 侧快照,枚举时填充;规格 §5.7.1)。 */
#ifndef MEOW_FONT_INFO_DEFINED
#define MEOW_FONT_INFO_DEFINED
typedef struct meow_font_info {
char family[64]; /* family slug = MeowOS/fonts/<family>/ 一级目录名 */
char name[64]; /* 显示名(index 无单列 → 回退 family) */
char weight[32]; /* weight slug(regular|bold|…,缺省 regular) */
char tier[8]; /* 档位 common|gbk|full(info 用) */
int glyph_count; /* font.json glyph_count(info 用) */
char label[128]; /* index 显示名(含字重 + 尺寸标记) */
int size_list[16]; /* 原生字号表(index 无 → 空) */
int size_count; /* 有效字号数 */
int bit_depth; /* 4|8(index 无 → 0) */
char path_png[320]; /* 卡根相对 MeowOS/fonts/<family>/<weight>/font.png */
} meow_font_info;
#endif
/* 卡根:env MEOW_CARD_ROOT 优先,否则默认 /usr/data/mnt/sd_0。 */
const char *meow_font_card_root(void);
/* <card_root>/MeowOS/config/fonts/index 绝对路径写入 out;0=成功。 */
int meow_font_index_path(char *out, int olen);
/* 读 index → 填充 out 数组(最多 max 条),返回「总条数」(无 index/不可读/空 → 1=合成默认行)。
* 注意 out[i].path_png 为「卡根相对」路径,需经卡根解析为绝对路径再使用。 */
int meow_font_index_load(meow_font_info *out, int max);
/* 应用可读 TF 卡字体列表(规格 §5.7.2):
* - get_available_count():可用字库数(含默认;无卡 → 1)。
* - enumerate(idx, out):按序号取,越界返回 0;idx=0=默认行(family=default)。
* - select_by_id(id):id=0 跟随系统默认(font.file,经 env MEOW_FONT_PNG/IDX);
* id>0 会话内固定用该套;该套字库缺失 → 降级默认(不丢请求)+ WARN 日志
* (meow_log→app 日志)。成功 0,越界负值。 */
int meow_font_get_available_count(void);
int meow_font_enumerate(int idx, meow_font_info *out);
int meow_font_select_by_id(int id);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_FONT_H */
+604
View File
@@ -0,0 +1,604 @@
/* meow_ipc.h — MeowOS IPC 协议定义(FRAMEWORK_DESIGN §1 / MEOWOS_API.md §1)。
*
* 客户端(meow_ipc 测试钩子)与守护进程(meow_launcherd)共用一份,杜绝两端漂移。
* 传输:AF_UNIX SOCK_STREAM,路径默认 /usr/data/meow_ipc.sock(可被 --ipc-sock /
* MEOW_IPC_SOCK 覆盖,供 qemu sim)。
* 帧格式:定长头(16B) + 变长负载,**全部小端 LE**(mipsel 原生)。
*
* 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 字节数
* };
*
* 本阶段(D · M0+M1+M2+M3+M4)通讯子集:MSG_HELLO/ACK/ERR + MSG_ACT_DECLARE/QUERY/RESULT +
* MSG_ACT_FOCUS/BACK + MSG_NOTIFY/PROGRESS/QUERY/DISMISS* + MSG_NAV(导航栈上报/退出)
* + MSG_META/MSG_PLAYCTL(媒体会话,阶段 D 附录 B)
* + MSG_REGISTER/SERVICE_OK/SERVICE_STOP/MSG_SYS(后台服务注册/停止/熔断事件,M4)。
* picker(0x0070/0x0071)已落地(二期)。
*/
#ifndef MEOW_IPC_H
#define MEOW_IPC_H
#include <stdint.h>
#include <stddef.h>
#define MEOW_IPC_MAGIC 0x4D4F5701u
#define MEOW_IPC_VERSION 1u
#define MEOW_IPC_PATH "/usr/data/meow_ipc.sock"
#define MEOW_IPC_SOCK_LEN 108 /* sockaddr_un.sun_path */
#define MEOW_IPC_MAX 4096u /* 单帧负载上限 */
#define MEOW_IPC_HDR_LEN 16u
/* 列表编码上限(count 个 NUL 字符串时,distinct 工作缓冲上限) */
#define MEOW_IPC_CARGO 1024u /* 守护进程入队拷贝上限(可小于 MEOW_IPC_MAX) */
/* ---- 消息类型(FRAMEWORK_DESIGN §1 表)---- */
enum {
MSG_NONE = 0x0000,
MSG_HELLO = 0x0001, /* ↑ 声明 app_id/版本/能力 */
MSG_ACK = 0x0002, /* ↓ 握手/应答 */
MSG_ERR = 0x0003, /* ↓ 错误码 */
MSG_REGISTER = 0x0010, /* ↑ 注册后台服务(保持连接) */
MSG_SERVICE_OK = 0x0011, /* ↓ 服务登记成功 */
MSG_SERVICE_STOP = 0x0012, /* ↑ 请求停止服务 */
MSG_NOTIFY = 0x0020, /* ↑ 推送/更新通知 */
MSG_NOTIFY_ACK = 0x0021, /* ↓ 落库结果 */
MSG_NOTIFY_DISMISS = 0x0022, /* ↑ 撤下通知 */
MSG_NOTIFY_LIST = 0x0023, /* ↓ 下发通知清单(重同步) */
MSG_NOTIFY_PROGRESS = 0x0024,/* ↑ 实时更新通知进度(仅改内存活跃槽,不落盘) */
MSG_NOTIFY_QUERY = 0x0025, /* ↑ 查询内存活跃通知集(MeowPanel 实时化前置) */
MSG_NOTIFY_DISMISS_ALL = 0x0026,/* ↑ 一键清除(保留 ongoing/media/progress 进行中,同通知中心 UI) */
MSG_NOTIFY_QUERY_RESULT = 0x0027, /* ↓ 活跃通知集序列化文本(JSON,字段同 TF 归档) */
MSG_NOTIF_OPEN = 0x0028, /* ↑ App 前台顶部下滑 → 请求 launcher 展开通知中心叠加会话(§10.5) */
MSG_NOTIF_CLOSE = 0x0029, /* ↑ App 告知结束/退出 → launcher 收尾兜底(可选用途,§10.5) */
MSG_ACT_DECLARE = 0x0030, /* ↑ (重)声明路由表 */
MSG_ACT_QUERY = 0x0031, /* ↑ 解析 activity 链路 */
MSG_ACT_RESULT = 0x0032, /* ↓ 返回链路 */
MSG_ACT_FOCUS = 0x0033, /* ↑ 上报当前顶层 activity(keep_awake 判定,M2.17) */
MSG_ACT_BACK = 0x0034, /* ↑ 上报回到根/无 activity(清 keep_awake,M2.17) */
MSG_NAV = 0x0040, /* ↑ 上报导航/请求退出 */
MSG_SHOW_ACTIVITY= 0x0041, /* ↓ 令前端应用显示某屏 */
MSG_PERF_QUERY = 0x0050, /* ↑ 性能/系统聚合查询(专项服务 meow_svc_perf) */
MSG_PERF_RESULT = 0x0051, /* ↓ 聚合 JSON(perf/system 子集) */
MSG_POWER_ACTION = 0x0060, /* ↑ 电源/系统动作信号(专项服务 meow_svc_power) */
MSG_POWER_STATUS = 0x0061, /* ↓ 动作受理/结果 + 状态文本 */
/* ---- picker:带返回值的跨 App 调用(M3 延伸,AMSD_DESIGN §6.2 二期已落地)----
* 语义:App A 经 MSG_PICKER_CALL 请求 App B 弹一个 selector 并返回所选值(如文件选择器)。
* amsd 为路由/决策者:它查 picker 表(app.json `picker.<action>=<chain>`)决定 handler App,
* 经 MSG_AMS_START(扩载荷含 picker 上下文)拉起 handler;handler 结果经 MSG_PICKER_RESULT
* 回传,launcher 转发 amsd 记录。属「跨 App 带返回值」调用。负载结构见下方
* m_picker_call_t / m_picker_result_t。 */
MSG_PICKER_CALL = 0x0070, /* ↑ 请求跨 App picker 调用(发起方 A → 持有方 B;→launcher→amsd) */
MSG_PICKER_RESULT = 0x0071, /* ↑ picker 返回值(候选结果回 A;→launcher→amsd) */
MSG_META = 0x0072, /* ↑ 媒体会话上报元数据/进度/状态(阶段 D 附录 B) */
MSG_PLAYCTL = 0x0073, /* ↓ 播放控制下发/↑ 控制器转发到最近活跃媒体会话 */
/* ---- amsd 控制(AMSD_DESIGN §4.2):amsd→launcher,申请拉起/终止某 App ----
* 语义:amsd 为「启动/终止」决策者 → launcher(执行器)执行。payload 见下。 */
MSG_AMS_START = 0x00A0, /* → 请求 launcher 拉起某 App(pkg + 可选 activity) */
MSG_AMS_KILL = 0x00A1, /* → 请求 launcher 终止某 App(SIGTERM 语义) */
/* ---- audiod 独占音频服务(devdocs/plan/AUDIOD_DESIGN.md §2):0x00C0-0x00CA ----
* 语义:App 只经 SDK 客户端 API(meow_ui_audio.c)喂 PCM,audiod 独占 hw:0,0。
* 独占+抢占(后开赢);软混音已否决(MIPS32 软 SRC 伤音质,留混音器接口位)。 */
MSG_AUDIO_OPEN = 0x00C0, /* ↑ 开流(m_audio_open;client 原生 rate/ch/fmt/flags) */
MSG_AUDIO_OPEN_ACK = 0x00C1, /* ↓ 授权(stream_id + grant_rate/ch/fmt + err;grant=客户端应产出的格式) */
MSG_AUDIO_WRITE = 0x00C2, /* ↑ PCM 字节流(按 grant 格式交织;单帧 ≤4096B,多帧连续发,无回执) */
MSG_AUDIO_PAUSE = 0x00C3, /* ↑ 暂停(u32 stream_id) */
MSG_AUDIO_RESUME = 0x00C4, /* ↑ 恢复(u32 stream_id) */
MSG_AUDIO_STOP = 0x00C5, /* ↑ 停止并关流(u32 stream_id) */
MSG_AUDIO_PREEMPTED= 0x00C6, /* ↓ 被抢占通知(m_audio_preempted;旧流被后开流赶走,App 收 UI 提示) */
MSG_AUDIO_QUERY = 0x00C7, /* ↑ 状态快照查询(空负载) */
MSG_AUDIO_STATE = 0x00C8, /* ↓ 状态快照文本(NUL 结尾;当前流/参数/帧数/underrun/路由/音量) */
MSG_AUDIO_ROUTE = 0x00C9, /* ↑ 手动路由(u32 port:0=auto 2=3.5 3=4.4;调试/面板用) */
MSG_AUDIO_VOLUME = 0x00CA, /* ↑ 音量(i32 pct:-1=查询 0-100=设置;v1 透传写 DAC numid=1/2) */
/* ---- meow_powermgr 功耗管理服务(devdocs/plan/POWER_MANAGER_DESIGN.md §6.1):0x00D0-0x00D7 ----
* 语义:功耗维度的查看/分析/管理(svc_power 管动作、svc_perf 管性能,powermgr 管功耗)。
* 独立 socket /usr/data/meow_pm.sock(--sock/MEOW_PM_SOCK 覆盖)。鉴权分级同 svc_power:
* QUERY/HISTORY/EVENTS=读级任意调用者;POLICY_SET=动作级(期 3 落地时接 SO_PEERCRED 同源代码)。 */
MSG_PM_QUERY = 0x00D0, /* ↑ 功耗聚合查询(m_pm_query_t{subset}:PM_SUBSET_* 位;0=全部) */
MSG_PM_RESULT = 0x00D1, /* ↓ 聚合 JSON(电池深加工/功耗估算/分解/策略,形状对齐 §3/§4.1) */
/* 0x00D2 MSG_PM_POLICY_GET / 0x00D3 MSG_PM_POLICY_SET —— 期 3(profile/低电阈值读改,SET 动作级鉴权)
* 0x00D4 MSG_PM_HISTORY(u32 hours)/ 0x00D5 MSG_PM_HISTORY_RESULT(统计 JSON)—— 期 2
* 0x00D6 MSG_PM_EVENTS / 0x00D7 MSG_PM_EVENTS_RESULT(异常耗电事件清单)—— 期 2 */
MSG_SYS = 0x00F0 /* ↓ 系统事件(守护关闭/服务死亡/播放器状态) */
};
/* ---- 返回码(MEOWOS_API.md §1,与 HTTP 层一致)---- */
enum {
MEOW_OK = 0,
MEOW_ERR_INVAL = -1,
MEOW_ERR_NOENT = -2,
MEOW_ERR_EXISTS = -3,
MEOW_ERR_PERM = -4,
MEOW_ERR_IO = -5,
MEOW_ERR_NOMEM = -6,
MEOW_ERR_NOTINIT = -7,
MEOW_ERR_BUSY = -8,
MEOW_ERR_TIMEOUT = -9,
MEOW_ERR_NODEV = -10,
MEOW_ERR_INTERNAL = -255
};
/* ---- HELLO flags(附录 A 声明式权限)---- */
#define MF_BACKGROUND 0x00000001u /* 可后台常驻 */
#define MF_PLAYBACK 0x00000002u /* 后台音频/播放 */
/* ---- MSG_META flags(元数据有效位)---- */
#define MF_ART 0x00000004u /* 封面/专辑图已提供 */
#define MF_LYRIC 0x00000008u /* 歌词已提供 */
#define MF_COVER 0x00000010u /* artwork 为可用路径/槽位 */
/* ---- 标识/长度 ---- */
#define MEOW_APP_ID_MAX 32
#define MEOW_ACT_MAX 64
#define MEOW_CHAIN_MAX 160
/* ---- 负载结构(全部 LE;mipsel 原生对齐,字段 4 字节对齐)---- */
/* MSG_HELLO ↑:应用声明 */
typedef struct m_hello {
char app_id[MEOW_APP_ID_MAX];
uint32_t version;
uint32_t flags;
uint32_t caps; /* 预留能力位 */
} m_hello_t; /* 44 B */
/* MSG_ACK ↓:握手/应答 */
typedef struct m_ack {
uint32_t code; /* 0=MEOW_OK */
uint32_t status; /* 附加(如已注册 app 数) */
} m_ack_t; /* 8 B */
/* MSG_ERR ↓:错误码 + 短消息 */
typedef struct m_err {
uint32_t code;
uint16_t msg_len;
char msg[64];
} m_err_t;
/* ================= 后台服务注册(M4,FRAMEWORK_DESIGN §9) = */
/* MSG_REGISTER ↑:无头后台服务注册。调用方(App 前台进程)须:
* ① app.json 声明 `background=true` 或 HELLO flags 含 MF_BACKGROUND(否则 ERR_PERM);
* ② app.json `service.<svc>=mode:restart:max:window_ms` 静态声明该服务(否则 ERR_NOENT);
* ③ 注册后保持 IPC 连接不断(launcher 以连接存活做熔断广播的投递判定)。
* svc=NUL 结尾服务名(≤15 字符);flags 按位:MF_BACKGROUND(申请后台常驻)。 */
typedef struct m_register {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
char svc[16]; /* 服务名(app.json service.<svc>) */
uint32_t flags; /* MF_BACKGROUND 等 */
} m_register_t; /* 52 B */
/* MSG_SERVICE_OK ↓:用 m_ack_t(code=0;status=服务子进程 pid)。 */
/* MSG_SERVICE_STOP ↑:请求停止自己已注册的服务(SIGTERM,不触发重启)。 */
typedef struct m_service_stop {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
char svc[16];
} m_service_stop_t; /* 48 B */
/* MSG_SYS ↓:系统事件广播(守护关闭/服务死亡/播放器状态)。
* event:MEOW_SYS_*;app_id/svc 为事件主体(SHUTDOWN 时可空)。 */
enum { MEOW_SYS_SHUTDOWN = 1, /* 守护进程即将关闭(关机/重启前回收) */
MEOW_SYS_SVC_DEAD = 2, /* 后台服务熔断(超 max_restart 不再拉起) */
MEOW_SYS_PLAYER_STATE = 3 }; /* 播放器状态变更(预留) */
typedef struct m_sys {
uint32_t event; /* MEOW_SYS_* */
char app_id[MEOW_APP_ID_MAX]; /* 32 */
char svc[16]; /* SVC_DEAD 时为熔断服务名 */
} m_sys_t; /* 52 B */
/* MSG_ACT_QUERY ↑:解析某 app 的 activity 链路 */
typedef struct m_act_query {
char app_id[MEOW_APP_ID_MAX];
char activity[MEOW_ACT_MAX];
} m_act_query_t; /* 96 B */
/* MSG_ACT_FOCUS ↑:上报当前顶层 activity(keep_awake 判定,M2.17) */
typedef struct m_act_focus {
char app_id[MEOW_APP_ID_MAX];
char activity[MEOW_ACT_MAX];
} m_act_focus_t; /* 96 B */
/* MSG_ACT_RESULT ↓:返回链路(root..target),depth=链路逻辑深度 */
typedef struct m_act_result {
uint32_t depth;
uint32_t code; /* MEOW_OK / MEOW_ERR_NOENT(act 未注册) */
uint16_t chain_len; /* chain 有效字节 */
uint16_t pad;
char chain[MEOW_CHAIN_MAX];
} m_act_result_t; /* 172 B */
/* MSG_ACT_DECLARE ↑:运行时声明路由表。app_id + count 个 NUL 结尾字符串,
* 每串形如 "<route_id>=<chain>"(如 "nowplaying=home;search;nowplaying")。
* 守护进程并集覆盖静态 app.json 路由。 */
typedef struct m_act_declare {
char app_id[MEOW_APP_ID_MAX];
uint16_t count;
uint16_t pad;
char entries[MEOW_IPC_CARGO - MEOW_APP_ID_MAX - 4];
} m_act_declare_t;
/* MSG_NAV nav_type 取值(FRAMEWORK_DESIGN §3 导航栈) */
enum { MEOW_NAV_REPORT = 0, /* 应用内逐屏回退/前进:上报当前栈深 + 顶层 activity */
MEOW_NAV_EXIT = 1 }; /* 应用在根屏按返回 → 请求启动器终止应用、回主屏 */
/* MSG_NAV ↑:上报导航/请求退出(M3 导航栈;launcher 主循环单写者消费)。
* - REPORT:应用弹/推自己的屏后上报;depth=当前逻辑深度(1..16),current=当前顶层 activity_id;
* - EXIT :应用在根屏再按返回;depth 置 0,current 可空。
* launcher 据此维护每应用 nav_stack(≤16 深),并在 EXIT 时终止前台应用会话。 */
typedef struct m_nav {
char app_id[MEOW_APP_ID_MAX];
uint32_t nav_type; /* MEOW_NAV_REPORT / MEOW_NAV_EXIT */
uint32_t depth; /* REPORT: 1..16;EXIT: 0 */
char current[MEOW_ACT_MAX]; /* REPORT: 当前顶层 activity_id;EXIT: 可空 */
} m_nav_t;
/* MSG_META ↑:媒体会话实时上报(阶段 D 附录 B;FRAMEWORK_DESIGN 附录 B 的 m_meta 微调落实)。
* 声明 MF_PLAYBACK 的 App 首次上报 → 注册为媒体源;后续更新(含 1s 级进度)。字段全 LE 定长。
* - state:0=停止 1=播放 2=暂停 3=缓冲。
* - flags:MF_ART/MF_LYRIC/MF_COVER(可多;声明哪类元数据有效)。
* - artwork/lyric:封面/歌词源(本地路径或 MeowOS 存储槽位);空=无(mf 位同时清)。
* - app_id:上报源头(与 HELLO 的 app_id 一致),launcher 据此归并同一会话。
* 边界:防越界(128 长度由 meow_ipc 双方同源 + 接收侧截断;payload < MEOW_IPC_CARGO)。 */
typedef 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[MEOW_APP_ID_MAX];
} m_meta_t; /* 128+128+128+16+192+192+32 = 828 B */
/* MSG_PLAYCTL ↓(launcher→App)/↑(控制器→launcher 转发到最近活跃媒体会话):播放控制。
* cmd:1=播放 2=暂停 3=上一首 4=下一首 5=seek 6=播放/暂停切换(toggle,源侧按当前态翻转);其余保留。
* seek_ms:cmd=5 时目标位置(ms);其余置 0。
* 语义:通知中心卡片/播放页按钮、物理媒体键 → meow_media_playctl(cmd,seek_ms) 经
* 「最近活跃媒体会话」的连接 fd 下发;宿主验证经 meow_ipc playctl 发到 launcher 转发。
* 物理播放/暂停键(164)在 SDK 侧恒映射 cmd=6(不再本地判 state:走自有 IPC 线程的源
* 不经 SDK meta 上报,SDK 侧 state 可能恒 0);launcher 透传 cmd 不改写。 */
typedef struct m_playctl {
uint32_t cmd; /* 1=播放 2=暂停 3=上一首 4=下一首 5=seek 6=播放/暂停toggle */
int64_t seek_ms; /* cmd=5: 目标位置 ms;否则 0 */
} m_playctl_t; /* 4 (+4 pad) + 8 = 16 B(mipsel int64 8 对齐) */
/* MSG_NOTIFY ↑:推送/更新通知(freedesktop 对齐 + MeowOS 扩展;定长 LE)。
* - summary/body/app_icon/expire_timeout 直通 freedesktop 字段;app_icon 即 SDK `icon`
* (icon name 或 path;映射为空串时 launcher 用该 app 默认图标回退);
* - target_activity/progress 为 MeowOS 专有(存储层映射为 hints 的
* meow.target_activity / meow.progress);
* - urgency 为 MeowOS 扩展(0-3,缺省 NORMAL;旧调用置 0=旧 pad 位);
* - actions[]/hints{} v1 走定长空串(M2b D-Bus 桥再填);media/ongoing 标记。
* 宿主:NOTIFICATION_SYSTEM.md §2/§4 + FRAMEWORK_DESIGN §4/附C。 */
typedef struct m_notify {
char app_id[MEOW_APP_ID_MAX]; /* 来源应用;系统事件="system" */
char category[24]; /* 通知类型(媒体通知="media") */
char summary[64];
char body[96];
char app_icon[48]; /* SDK icon;空=launcher 按 app_id 回退 app 图标 */
char target_activity[MEOW_ACT_MAX]; /* MeowOS:点击跳转目标 activity */
uint32_t replaces_id; /* 0=新建;>0=替换已存在通知 */
uint32_t expire_timeout; /* ms;0xFFFFFFFF=ONGOING 常驻 */
int32_t progress; /* MeowOS:0-100;<0=无 */
uint8_t media; /* 1=媒体通知 */
uint8_t ongoing; /* 1=常驻通知 */
uint8_t urgency; /* 0-3(低/普通/高/紧急);越界由 SDK 钳位缺省 NORMAL;旧调用置 0=旧 pad 位 → LOW/静默 */
uint8_t pad;
} m_notify_t; /* 定长 LE;尾部 4 字节(media/ongoing/urgency/pad)与旧版 pad 等宽 */
/* MSG_NOTIFY_PROGRESS ↑:实时更新一条已存在通知的进度(仅改 launcher 内存活跃槽,
* 不落盘——TF 快照只在创建/结束(100% 或 dismiss)写)。 */
typedef struct m_notify_progress {
uint32_t nid; /* launcher 分配的通知 id(MSG_NOTIFY_ACK.status) */
int32_t progress; /* 0-100;<0=清除进度条 */
} m_notify_progress_t; /* 8 B */
/* MSG_NOTIFY_QUERY_RESULT ↓:活跃通知集序列化文本(JSON 数组;NUL 结尾)。
* 字段与 TF 归档一致:id/app_id/category/summary/body/urgency/ts/progress/ongoing/media/
* target_activity(+app_icon)。payload 定长 LE,整个结构 < MEOW_IPC_MAX。 */
typedef struct m_notify_query_result {
uint32_t code; /* MEOW_OK / MEOW_ERR_* */
uint16_t text_len; /* text 有效字节(不含 NUL) */
uint16_t pad;
char text[MEOW_IPC_MAX - 12]; /* 序列化 JSON 数组 */
} m_notify_query_result_t; /* 4096 B */
/* ================= App 前台划出通知中心(FRAMEWORK_DESIGN §10.5) = */
/* MSG_NOTIF_OPEN ↑(App→launcher):App 进程内顶部下滑(MEOW_EV_NOTIF_PULL),请求 launcher
* 展开通知中心叠加会话。App 只检测+上报、**不渲染系统 UI**(MEOW_APP_SDK §6.1 ③)。
* 负载字段全 LE 定长。 */
typedef struct m_notif_open {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
uint32_t event_seq; /* App 侧事件序号(防重放/去抖,可选;0=填充默认) */
uint16_t origin_x; /* 手势按下原点 X(防御性校验:应≈顶部,best-effort 可 0) */
uint16_t origin_y; /* 手势按下原点 Y(launcher 复核是否在顶部热区) */
uint16_t hotzone; /* 上报时 SDK 的热区高(28 或 4,见 meow_ui_statusbar_hotzone) */
uint8_t flags; /* 预留:位0=App 声明 fullscreen */
uint8_t pad;
} m_notif_open_t; /* 32+4+2+2+2+1+1 = 44 B(LE,4 字节对齐) */
/* MSG_NOTIF_CLOSE ↑(App→launcher,可选用途):App 告知结束/退出,launcher 收尾兜底
* (清 active 标记/SIGCONT 兜底)。非可靠链路:launcher 主要靠 waitpid/kill(pid,0) 自感知。 */
typedef struct m_notif_close {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
uint32_t reason; /* 0=App 主动退出;1=App 请求关闭通知中心;2=App 崩溃 */
} m_notif_close_t; /* 32+4 = 36 B */
/* ================= 专项服务 IPC(SYSTEM_FRAMEWORK_SERVICES §2.2/§2.3)= */
/* ---- MSG_PERF_QUERY 子集位(0=全部)---- */
#define PERF_SUBSET_PERF (1u << 0) /* cpu/mem/uptime/temp/storage/tfcard */
#define PERF_SUBSET_SYSTEM (1u << 1) /* system(version/hostname/kernel/arch) */
/* MSG_PERF_QUERY ↑:性能/系统聚合查询(服务端 meow_svc_perf) */
typedef struct m_perf_query {
uint32_t subset; /* 0=全部;PERF_SUBSET_* 组合 */
} m_perf_query_t; /* 4 B */
/* MSG_PERF_RESULT ↓:聚合 JSON(payload 为 NUL 结尾 JSON 文本) */
typedef struct m_perf_result {
uint32_t code; /* MEOW_OK / MEOW_ERR_* */
uint32_t subset; /* 回显请求 subset */
uint16_t json_len; /* json 有效字节(不含 NUL) */
uint16_t pad;
char json[MEOW_IPC_MAX - 12]; /* 聚合 JSON(.data 形状,§2.2) */
} m_perf_result_t;
/* ---- POWER_* 动作枚举(m_power_action_t.cmd;与 CLI §2.4 同源)---- */
enum {
POWER_SHUTDOWN = 0, /* 关机 */
POWER_REBOOT = 1, /* 重启回 MeowOS(强制写 boot_default=0) */
POWER_UPGRADE = 2, /* 写 mtd5=ota:kernel2 进升级模式 */
POWER_BACK_HIBY = 3, /* 写 boot_default=1 + reboot(回 HiBy) */
POWER_SET_DEFAULT_MEOW = 4, /* 只写 boot_default=0,不重启 */
POWER_SET_DEFAULT_HIBY = 5, /* 只写 boot_default=1,不重启 */
POWER_STATUS = 6, /* 综合状态查询 */
POWER_BATTERY = 7, /* 电池查询 */
POWER_REBOOT_REASON = 8, /* 上次重启原因 */
POWER_UPGRADE_STATUS = 9, /* 升级标志(mtd5=ota:kernel2?) */
POWER_SCREEN = 10, /* 屏幕电源:flag 0=off/1=on/2=timeout(秒取 arg) */
POWER_DAC = 11 /* DAC:flag 0=off/1=on/2=status */
};
/* MSG_POWER_ACTION ↑:电源/系统动作信号(服务端 meow_svc_power) */
typedef struct m_power_action {
uint32_t cmd; /* POWER_* 枚举 */
uint32_t flag; /* 随 cmd;POWER_SCREEN/DAC 用 */
char arg[32]; /* 可选文本参数(如 screen timeout 秒数字符串) */
} m_power_action_t; /* 40 B */
/* MSG_POWER_STATUS ↓:动作受理/结果 + 状态文本(CLI/IPC 展示) */
typedef struct m_power_status {
uint32_t code; /* MEOW_OK / MEOW_ERR_PERM / MEOW_ERR_INVAL / MEOW_ERR_NODEV */
uint32_t cmd; /* 回显 cmd */
uint16_t msg_len; /* msg 有效字节(不含 NUL) */
uint16_t pad;
char msg[96]; /* 结果/状态文本 */
} m_power_status_t;
/* ---- meow_powermgr 功耗管理(POWER_MANAGER_DESIGN §6.1;服务端 meow_powermgr)---- */
/* MSG_PM_QUERY 子集位(0=全部) */
#define PM_SUBSET_BATTERY (1u << 0) /* 电池深加工:state/pct/mv/health/续航估算 */
#define PM_SUBSET_ESTIMATE (1u << 1) /* 当前功耗估算:est_mw + confidence(estimated/derived) */
#define PM_SUBSET_BREAKDOWN (1u << 2) /* 功耗分解:各子系统分量(§3.2 经验模型,系数待标定) */
#define PM_SUBSET_POLICY (1u << 3) /* 策略档位快照(期 3;期 1 恒 null) */
/* MSG_PM_QUERY ↑:功耗聚合查询 */
typedef struct m_pm_query {
uint32_t subset; /* 0=全部;PM_SUBSET_* 组合 */
} m_pm_query_t; /* 4 B */
/* MSG_PM_RESULT ↓:聚合 JSON(payload 为 NUL 结尾 JSON 文本,同 m_perf_result_t 口径) */
typedef struct m_pm_result {
uint32_t code; /* MEOW_OK / MEOW_ERR_* */
uint32_t subset; /* 回显请求 subset */
uint16_t json_len; /* json 有效字节(不含 NUL) */
uint16_t pad;
char json[MEOW_IPC_MAX - 12]; /* 聚合 JSON(§3/§4.1 形状) */
} m_pm_result_t;
/* ---- amsd 控制(AMSD_DESIGN §4.2)---- */
/* MSG_AMS_START →:请求 launcher 拉起某 App。app_id=包名(权威);activity 空=裸启动
* (launcher launch_app),非空=resolve_chain+launch_activity。
* picker 上下文(二期):picker=1 时本次启动为「picker handler 调用」——launcher 注入 env
* MEOW_PICKER_ACTION/MEOW_PICKER_REQ_ID/MEOW_PICKER_CALLER 到子进程;handler App 据此进入
* picker 模式,选完后经 MSG_PICKER_RESULT 回传。 */
typedef struct m_ams_start {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
char activity[MEOW_ACT_MAX]; /* 64;空=裸启动 */
uint32_t picker; /* 1=带 picker 上下文(注入 MEOW_PICKER_*) */
uint32_t picker_req_id; /* picker 请求号(回显到结果) */
char picker_action[24]; /* picker action(如 "pick_file");picker=0 忽略 */
char picker_caller[MEOW_APP_ID_MAX]; /* 32:发起方 app_id(""=系统/CLI) */
} m_ams_start_t; /* 160 B */
/* MSG_AMS_KILL →:请求 launcher 终止某 App(SIGTERM 语义,执行器=launcher)。 */
typedef struct m_ams_kill {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
} m_ams_kill_t; /* 32 B */
/* ---- picker 负载(二期)---- */
/* MSG_PICKER_CALL ↑:发起跨 App picker 调用(App A → launcher → amsd 路由;或 amsd 内部)。
* caller=发起方 app_id(""=系统/CLI);req_id=调用方自填(结果/PICKER_RESULT 回显);
* action=要调用的 picker 类型(如 "pick_file");hint=初始目录等提示(空=缺省)。 */
typedef struct m_picker_call {
char caller[MEOW_APP_ID_MAX]; /* 32 */
uint32_t req_id; /* 调用方请求号 */
char action[24]; /* picker action */
char hint[128]; /* 提示(初始目录等);空=缺省 */
uint32_t flags; /* 预留 */
} m_picker_call_t; /* 192 B */
/* MSG_PICKER_RESULT ↑:picker 返回值(handler App → launcher → amsd)。caller/req_id/action
* 回显调用方;code=MEOW_OK/MEOW_ERR_*;value=返回项(路径/文本;空=用户取消)。 */
typedef struct m_picker_result {
char caller[MEOW_APP_ID_MAX]; /* 32:回显发起方(""=系统/CLI) */
uint32_t req_id; /* 回显请求号 */
char action[24]; /* 回显 action */
uint32_t code; /* MEOW_OK / MEOW_ERR_* */
char value[256]; /* 返回项(路径/文本);空=cancel */
} m_picker_result_t; /* 320 B */
/* ================= audiod 独占音频服务(AUDIOD_DESIGN.md) = */
/* PCM 格式枚举(客户端原生 fmt 与 grant_fmt 共用):1=S16_LE 2=S24_LE 3=S32_LE 4=FLOAT_LE。
* v1 实装 S16/S32(S16 直通 + S32 升位);S24 按 32-in-32 处理;FLOAT v1 拒绝。 */
enum {
AUDIO_FMT_S16 = 1,
AUDIO_FMT_S24 = 2,
AUDIO_FMT_S32 = 3,
AUDIO_FMT_FLOAT = 4
};
/* MSG_AUDIO_OPEN ↑:请求开流(App 原生声源参数)。grant_*(ACK)回 audiod 实际授权给客户端的
* 产出格式(率/声道/位深)——客户端必须按 grant 格式产出 PCM(SDK meow_ui_audio 负责归一:
* mono→stereo 复制 / S16↔S32 定值升降位)。ch>2 或 FLOAT → ERR_INVAL。 */
typedef struct m_audio_open {
char app_id[MEOW_APP_ID_MAX]; /* 32 */
uint32_t rate; /* 原生采样率(应用源,如 44100/48000) */
uint16_t ch; /* 原生声道数(1=mono 2=stereo) */
uint16_t fmt; /* 原生格式(AUDIO_FMT_*) */
uint32_t flags; /* 预留(0) */
} m_audio_open_t; /* 32+4+2+2+4 = 44 B */
/* MSG_AUDIO_OPEN_ACK ↓:授权结果。err=MEOW_OK 才有效(stream_id>0 且 grant_* 为实际授权值);
* err<0 时 stream_id=0、grant_* 视为无效(客户端 open 返回负错误码)。 */
typedef struct m_audio_open_ack {
uint32_t stream_id; /* 授权流 id(>0) */
uint32_t grant_rate; /* 客户端应产出的采样率(=客户端 rate,无 SRC) */
uint16_t grant_ch; /* 客户端应产出的声道数(DAC 双声道 → 通常 2) */
uint16_t grant_fmt; /* 客户端应产出的格式(AUDIO_FMT_*,=硬件最优) */
int32_t err; /* MEOW_OK / MEOW_ERR_INVAL / MEOW_ERR_NODEV / MEOW_ERR_BUSY 等 */
} m_audio_open_ack_t; /* 4+4+2+2+4 = 16 B */
/* MSG_AUDIO_PAUSE/RESUME/STOP ↑:流控制(按 stream_id 定位)。 */
typedef struct m_audio_stream {
uint32_t stream_id;
} m_audio_stream_t; /* 4 B */
/* MSG_AUDIO_PREEMPTED ↓:被抢占通知(后开流赢;旧流收此消息,App 应暂停 UI/提示)。
* 旧流仍可读但 PCM 被丢弃(draining),直到客户端 CLOSE/断开。 */
typedef struct m_audio_preempted {
uint32_t stream_id; /* 被抢占的流 id */
char by_app[MEOW_APP_ID_MAX]; /* 32:抢占者 app_id */
} m_audio_preempted_t; /* 4+32 = 36 B */
/* MSG_AUDIO_ROUTE ↑:手动切换输出路由(调试/面板用)。port:0=auto(跟随插孔) 2=3.5 3=4.4。 */
typedef struct m_audio_route {
uint32_t port; /* 0=auto 2=3.5 3=4.4 */
} m_audio_route_t; /* 4 B */
/* MSG_AUDIO_VOLUME ↑:音量查询/设置。pct<0(-1)=查询当前音量;0-100=设置(写 DAC numid=1/2
* + 持久化 settings.conf `audio.volume`,与 watchdog/launcher 同源同键)。 */
typedef struct m_audio_volume {
int32_t pct; /* -1=查询;0-100=设置 */
} m_audio_volume_t; /* 4 B */
/* ================= meow_netmgrd 网络管理服务(devdocs/plan/NETMGR_DESIGN.md §3/§10)=====
* 语义:接口统一层(WiFi/BT/USB-eth/rfkill/IP/路由/DNS 只读)查询与控制的系统权威。
* 独立 socket /usr/data/meow_net.sock(--sock/MEOW_NET_SOCK 覆盖)。进程形态对齐 powermgr:
* svcd 托管 trigger=boot + 单一二进制双形态(/usr/bin/meow_netmgrd 守护 + /usr/bin/meow_net CLI)。
* 鉴权分级同 svc_power(§10/期1):读级(STATUS/IFACE、WIFI_CTL 内 status/networks、BT_CTL 内
* status/paired)任意调用者;写级(WIFI_CTL 内 scan/connect/disconnect/on/off/rfkill_set/udhcpc、
* BT_CTL 内 on/off)仅系统身份(SO_PEERCRED → /usr/bin/meow_* 或 os.meow.* 包)。
* HibyOS 模式(/tmp/meow_boot_mode=hiby):读级可查,写级拒 + 记日志。
* 期 1 实装 0x00E0-0x00E7;0x00E8-0x00EF 保留(期2:连接普查/DNS 代理;期3:管控策略/事件推送)。 */
enum { /* 与主 enum 分列,追加式不改既有行 */
MSG_NET_STATUS_REQ = 0x00E0, /* ↑ 概览查询(空负载=全部) */
MSG_NET_STATUS_RESULT = 0x00E1, /* ↓ 概览 JSON */
MSG_NET_IFACE_REQ = 0x00E2, /* ↑ 接口列表/详情(name 空=全部) */
MSG_NET_IFACE_RESULT = 0x00E3, /* ↓ 接口 JSON */
MSG_NET_WIFI_CTL = 0x00E4, /* ↑ 子命令字串(scan/connect/... + rfkill/udhcpc) */
MSG_NET_WIFI_RESULT = 0x00E5, /* ↓ 结果/文本 */
MSG_NET_BT_CTL = 0x00E6, /* ↑ 子命令字串(status/on/off/paired) */
MSG_NET_BT_RESULT = 0x00E7 /* ↓ 结果/文本 */
/* 0x00E8-0x00EF 保留:0xE8 连接表 / 0xEA 策略读写 / 0xEC DNS 控制 / 0xEE 事件推送(期 2/3) */
};
/* MSG_NET_STATUS_REQ ↑(空负载=全部;预留 subset 位,期 1 恒 0)→ MSG_NET_STATUS_RESULT ↓:
* 概览 JSON(mode/ifaces[]/wifi/bt/rfkill[],见 NETMGR_DESIGN §3 统一模型)。*/
typedef struct m_net_status_result {
uint32_t code; /* MEOW_OK / MEOW_ERR_* */
uint16_t json_len; /* json 有效字节(不含 NUL) */
uint16_t pad;
char json[MEOW_IPC_MAX - 8]; /* 概览 JSON(.data 形状) */
} m_net_status_result_t;
#define NET_IFACE_NAME_MAX 32 /* 接口名上限(lo/wlan0/usb-eth) */
/* MSG_NET_IFACE_REQ ↑:name 空=全部接口;否则单接口详情。→ MSG_NET_IFACE_RESULT ↓。 */
typedef struct m_net_iface_req {
char name[NET_IFACE_NAME_MAX];
} m_net_iface_req_t; /* 32 B */
typedef struct m_net_iface_result {
uint32_t code;
uint16_t json_len;
uint16_t pad;
char json[MEOW_IPC_MAX - 8];
} m_net_iface_result_t;
/* MSG_NET_WIFI_CTL / MSG_NET_BT_CTL ↑:子命令字串 + 变长 arg(connect 的 ssid/psk)。→ *_RESULT ↓。
* cmd(WIFI_CTL): status|scan|networks|connect|disconnect|on|off + rfkill/udhcpc 命名空间
* (rfkill arg="list"|"<type> <on|off>";udhcpc arg="renew <if>"|"release <if>")。
* cmd(BT_CTL) : status|on|off|paired。 */
typedef struct m_net_cmd {
char cmd[24]; /* 子命令字串(大写不敏感;接收侧截断) */
char arg[132]; /* connect: "<ssid>[,<psk>]";rfkill: "<type> <on|off>";udhcpc: "renew|release <if>" */
} m_net_cmd_t; /* 156 B */
typedef struct m_net_cmd_result {
uint32_t code; /* MEOW_OK / MEOW_ERR_PERM / MEOW_ERR_INVAL / MEOW_ERR_NODEV */
uint16_t text_len; /* text 有效字节(不含 NUL) */
uint16_t pad;
char text[MEOW_IPC_MAX - 8];
} m_net_cmd_result_t;
/* ---- 期 2:观测层(连接普查)+ DNS 代理(NETMGR_DESIGN §4/§5)----
* 0x00E8/0x00EC 实现取代上方「0x00E8-0x00EF 保留」注释中的连接表/DNS 控制两项;
* 0x00EA(策略读写,期3)/0x00EE(事件推送,期2 订阅制预留)仍保留未实装。 */
enum { /* 与主 enum 分列,追加式不改既有行 */
MSG_NET_CONNS_REQ = 0x00E8, /* ↑ 连接表查询(entity 空=全部) */
MSG_NET_CONNS_RESULT = 0x00E9, /* ↓ 连接表文本(定长行;超帧截断标记) */
MSG_NET_DNS_CTL = 0x00EC, /* ↑ dns status|stats|flush */
MSG_NET_DNS_RESULT = 0x00ED /* ↓ 结果/统计文本 */
/* 0x00EA 策略读写(期3)/ 0x00EE 事件推送(预留,期2 订阅制)/ 0xEB、0xEF 余量 */
};
/* MSG_NET_CONNS_REQ ↑:entity 前缀过滤(空=全部)。entity 形如 `app:<pkg>`/`svc:<svc>`/`proc:<comm>`。 */
typedef struct m_net_conns_req {
char entity[48];
} m_net_conns_req_t; /* 48 B */
/* MSG_NET_CONNS_RESULT ↓:连接表文本(每行 `entity|lip:lport|rip:rport|state|age_s|domain`)。
* 超单帧上限时截断并置 truncated=1(app/top 由客户端按行聚合,容纳全部)。 */
typedef struct m_net_conns_result {
uint32_t code; /* MEOW_OK / MEOW_ERR_* */
uint16_t text_len;
uint16_t truncated; /* 1=被截断 */
char text[MEOW_IPC_MAX - 8];
} m_net_conns_result_t;
/* MSG_NET_DNS_CTL ↑:cmd=status|stats|flush。status/stats 读级任意;flush(清缓存)为动作级系统身份。 */
typedef struct m_net_dns_ctl {
char cmd[16];
} m_net_dns_ctl_t; /* 16 B */
typedef struct m_net_dns_result {
uint32_t code;
uint16_t text_len;
uint16_t pad;
char text[MEOW_IPC_MAX - 8];
} m_net_dns_result_t;
#endif /* MEOW_IPC_H */
+168
View File
@@ -0,0 +1,168 @@
/* meow_notif.h — MeowOS 通知存储 + 分发(阶段 D · M2a)
*
* 定位:MeowOS 通知中心后端(存储 + 分发),是阶段 B 通知中心 UI(M5)+ 阶段 D
* (M2b D-Bus 桥 / M2c 转储 TF 卡)的前提。设计规范:NOTIFICATION_SYSTEM.md §1-§8
* + FRAMEWORK_DESIGN §4/附C(freedesktop.org Desktop Notifications)。
*
* 本批(M2a)只做核心存储骨架:
* - 通知数据结构(对齐 freedesktop 字段 + MeowOS 扩展 target_activity/progress);
* - 内存配额(每 App ≤ notify.categories 个类型;每类型活跃 ≤ notify.category_quota;
* 媒体通知每 App ≤ notify.media_quota,允许多媒体 App 同时);
* - TTL 10s 转储钩子(设计 §8,实际 TF 落盘 M2c 后置,本批预留 notif_dump_cb);
* - 原生 IPC 通道接入点(MSG_NOTIFY→ACK / MSG_NOTIFY_DISMISS→ACK;MSG_NOTIFY_LIST
* 为守护→App 下发,本批提供序列化 helper,UI(M5) 接入)。
*
* 空洞实现风格:本文件自包含(不依赖 launcher 主模块的 logmsg/now_ms —— 二者现归 util.c,可经
* meow_launcher_internal.h 引用),配额从 meow_settings 读(B2a;键缺省时用本文件默认值)。
* 注释风格中文 +「M2.a 说明」。
*/
#ifndef MEOW_NOTIF_H
#define MEOW_NOTIF_H
#include <stdint.h> /* uint32_t/uint64_t/int32_t */
#include <stddef.h> /* size_t */
#ifdef __cplusplus
extern "C" {
#endif
/* == 返回码(对齐 meow_ipc.h / MEOWOS_API.md §1,通知专用枚举)== */
enum {
NOTIF_OK = 0,
NOTIF_ERR_INVAL = -1, /* 参数非法 */
NOTIF_ERR_NOMEM = -6, /* 槽满/内存不足 */
NOTIF_ERR_NOTINIT = -7, /* 未 init */
NOTIF_ERR_QUOTA = -12, /* 配额超限(App 类型数 / 类型条数 / 媒体数) */
NOTIF_ERR_NOENT = -2, /* 通知 id 不存在 */
NOTIF_ERR_IO = -5 /* 文件/存储 IO 失败(TF 转储,无卡/不可写) */
};
/* == 容量/长度(单设备上限;定长,控制静态内存)== */
#define MEOW_NOTIF_APP_ID_MAX 32
#define MEOW_NOTIF_CAT_MAX 24
#define MEOW_NOTIF_SUMMARY_MAX 64
#define MEOW_NOTIF_BODY_MAX 96
#define MEOW_NOTIF_ICON_MAX 48
#define MEOW_NOTIF_ACTIVITY_MAX 48
#define MEOW_NOTIF_ACTIONS_MAX 96 /* NUL 分隔动作键列表 */
#define MEOW_NOTIF_HINTS_MAX 96 /* 原始 "k=v;..." 提示串 */
/* == 配额默认(运行时从 meow_settings notify.* 覆盖;键缺省用此)== */
#define MEOW_NOTIF_CATS_DEF 4 /* 每 App 最多申请的通知类型数(notify.categories) */
#define MEOW_NOTIF_CAT_QUOTA_DEF 4 /* 每类型活跃(未过期)通知上限(notify.category_quota) */
#define MEOW_NOTIF_MEDIA_QUOTA_DEF 1 /* 每 App 媒体通知上限(notify.media_quota) */
#define MEOW_NOTIF_TTL_MS 10000 /* 设计 §8:通知创建 10s 后自动转储到 TF */
/* 媒体通知(category)约定名:命中即按 notify.media_quota 约束(单 App 1 条) */
#define MEOW_NOTIF_MEDIA_CAT "media"
/* 系统事件作为 App 的 app_id(NOTIFICATION_SYSTEM.md §7:系统也抽象为 App,同样走配额) */
#define MEOW_NOTIF_SYSTEM_APP "system"
/* 通知结构(对齐 freedesktop + MeowOS 扩展)。
* fields 注释:NOTIFICATION_SYSTEM.md §4。 */
typedef struct meow_notif {
uint32_t id; /* 全局递增通知 id(0=无效/未分配) */
char app_id[MEOW_NOTIF_APP_ID_MAX]; /* 来源应用;系统事件="system" */
char category[MEOW_NOTIF_CAT_MAX]; /* 通知类型(媒体通知="media") */
char summary[MEOW_NOTIF_SUMMARY_MAX]; /* 标题(单行) */
char body[MEOW_NOTIF_BODY_MAX]; /* 正文(可多行) */
char app_icon[MEOW_NOTIF_ICON_MAX]; /* 图标 icon name 或 path(SDK icon;空→app 图标回退) */
char actions[MEOW_NOTIF_ACTIONS_MAX]; /* actions[](NUL 分隔;v1 空,M2b 填) */
char hints[MEOW_NOTIF_HINTS_MAX]; /* hints{} 原始 "k=v;..." 串(v1 空,M2b 填) */
uint32_t expire_timeout; /* 超时 ms;0xFFFFFFFF=ONGOING 常驻 */
uint64_t created_ms; /* 创建时刻(墙钟 epoch ms,供归档/显示) */
uint64_t dump_at_ms; /* 转储时刻(monotonic ms,TTL=创建+10s;ONGOING 亦到此转储) */
int32_t progress; /* MeowOS:0-100 进度;<0=无(实时仅改内存,落盘只在创建/结束) */
char target_activity[MEOW_NOTIF_ACTIVITY_MAX]; /* MeowOS:点击跳转目标 activity */
uint8_t urgency; /* 紧急度 0-3(低/普通/高/紧急);缺省 NORMAL */
uint8_t ongoing; /* 1=常驻通知(服务死随清) */
uint8_t media; /* 1=媒体通知(走 notify.media_quota) */
uint8_t dismissed; /* 1=已撤下 */
uint8_t dumped; /* 1=已转储(归档) */
uint8_t active; /* 1=槽位占用 */
} meow_notif_t;
/* 转储回调(M2c 落盘 / 本批默认仅日志):通知归档时调用。 */
typedef void (*meow_notif_dump_cb)(const meow_notif_t *n);
/* 图标回退回调:post 的 n->app_icon 为空时调用,按 app_id 填该 app 默认图标(name/path)。
* 返回 1=已填 out;0/空=无(通知中心 UI 再回退)。NULL=禁用回退(保持空 app_icon)。 */
typedef int (*meow_notif_icon_cb)(const char *app_id, char *out, size_t outsz);
/* == 生命周期 == */
int meow_notif_init(void); /* 幂等;从 meow_settings 读 notify.* 配额(B2a) */
int meow_notif_shutdown(void); /* 保存/清理(进程退出前调;本批=归档未转储项) */
/* == 核心 API == */
/* 推送/更新通知。n->id 为 0(新建);若 n->id>0 或 replace 语义,
* 按 n 中同 id 更新已存在通知(未找到则新建)。返回 NOTIF_OK/NOTIF_ERR_*;
* *out_id 返回分配/更新的通知 id(可为 NULL)。 */
int meow_notif_post(const meow_notif_t *n, uint32_t *out_id);
/* 撤下通知(dismiss)。随之为该通知归档(未转储则立即调 dump_cb + 标记),并释放槽。 */
int meow_notif_dismiss(uint32_t id);
/* 活跃(未转储)通知数。app_id 为 NULL/空=全部。 */
int meow_notif_count(const char *app_id);
/* 遍历(回调)当前通知。app_id 为 NULL/空=全部。返回遍历到的条数;
* 回调返回非 0 则中止遍历。 */
int meow_notif_list(const char *app_id,
int (*cb)(const meow_notif_t *n, void *ctx), void *ctx);
/* 立即转储所有未上卡(未 dumped)通知:逐条调 dump_cb + 标 dumped(不释放;
* 停机前转储用)。返回转储条数。 */
int meow_notif_dump_now(void);
/* 主循环周期调(每 10ms 排空 TODO):TTL 到期 → 归档 + (非 ONGOING)释放槽;
* dismissed 且未转储 → 归档 + 释放;ONGOING 转储后仍保留内存(服务死随清)。 */
void meow_notif_tick(void);
/* 正常电源事件(关机/重启)前调用:先转储所有未上卡通知,再清板载。 */
void meow_notif_before_poweroff(void);
/* 覆盖转储回调(NULL=恢复默认日志;M2c 接 TF 落盘)。 */
void meow_notif_set_dump_cb(meow_notif_dump_cb cb);
/* 覆盖图标回退回调(NULL=禁用,空 app_icon 保持空;M5 通知中心 UI 再回退)。 */
void meow_notif_set_icon_cb(meow_notif_icon_cb cb);
/* 实时更新一条活跃通知的进度(0-100,<0=清除)。仅改内存活跃槽;progress>=100 视为「结束」,
* 立即归档(落盘快照)并(非 ONGOING)释放槽——对应「里程碑落盘」。返回 NOTIF_OK/NOTIF_ERR_NOENT。 */
int meow_notif_update_progress(uint32_t id, int progress);
/* 一键清除(MSG_NOTIFY_DISMISS_ALL / 通知中心 UI 同语义):dismiss 所有「可清除」活跃通知
* (非 ongoing / 非 media / 无进行中进度 progress<0——红线段一律保留)。每条 dismiss = 归档留档
* + 释放槽。返回清除条数;<0=错误(NOTIF_ERR_*)。 */
int meow_notif_clear_active(void);
/* 把当前活跃通知集序列化为 JSON 数组文本写入 buf(≤buf_len,NUL 结尾)。app_id 空/NULL=全部,
* 非空=仅该 app 的活跃通知。字段同 TF 归档:id/app_id/category/summary/body/urgency/ts/
* progress/ongoing/media/target_activity(+app_icon);ts=created_ms(epoch ms)。
* 返回文本字节数(不含 NUL);<0=错误(NOTIF_ERR_*)。 */
int meow_notif_serialize_json(const char *app_id, char *buf, int buf_len);
/* == TF 卡转储(通知#6 / M2c,NOTIFICATION_SYSTEM.md §5/§8 + MEOWOS_SPEC_REF §5.3)==
* 把 dump_cb 接到 meow_notif_dump_tf 即把每条通知追加为一行 CSV 到
* <卡根>/MeowOS/notifications/notifications.log,并按日志总大小滚动截断
* (保留最新 10MB,不被电源事件清;启动时 meow_notif_init 先清板载+内存表)。
* 字段按 meow_notif 结构(title<-summary;app_icon<-SDK icon 空→app 图标回退;urgency 0-3;
* progress 当前值,-1=无;均做 CSV 转义/去换行)。无卡/不可写仅打点降级,绝不崩。 */
int meow_notif_dump_tf(const meow_notif_t *n); /* 0=成功;负=失败(无卡/IO/参数) */
void meow_notif_clear_tf(void); /* 开机清板载通知(清空文件,保留目录) */
void meow_notif_set_tf_path(const char *path); /* 覆盖转储日志路径;NULL=恢复默认卡路径(宿主单测用) */
void meow_notif_set_tf_max(size_t max_bytes); /* 覆盖滚动截断上限;0=恢复默认 10MB(宿主单测用) */
/* 调试:打印当前 Active 表/App 表(前缀)。 */
void meow_notif_dump(const char *log_prefix);
/* MSG_NOTIFY_LIST(守护→App 下发清单,M5 通知中心/重同步用):
* 把 app_id 的当前通知序列化为 MSG_NOTIFY_LIST 负载写入 buf(≤MEOW_IPC_CARGO),
* 返回负载字节数;<0=无(app 无通知)。 */
int meow_notif_serialize_list(const char *app_id, uint8_t *buf, int buf_len);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_NOTIF_H */