169 lines
10 KiB
C
169 lines
10 KiB
C
/* 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 */
|