通知模型补全(agent-107: SDK icon+update_progress / IPC urgency+MSG_NOTIFY_PROGRESS / 存储 urgency+icon回退+progress / CSV加3列) + 全屏收合视觉+滑条(agent-108)
This commit is contained in:
1 parent
663b0aa11d
commit
a8cd9fe5dc
9 files changed
+176
-29
No files matched your search
+42
-3
@@ -6,13 +6,15 @@
|
||||
* meow_ipc.h(同源一份、杜绝两端漂移):
|
||||
* - 帧头 16B:magic=0x4D4F5701 / version=1 / type / req_id / len(全小端 LE,mipsel 原生);
|
||||
* - MSG_NOTIFY(0x0020) ↑ 负载 = m_notify_t;MSG_NOTIFY_ACK(0x0021) ↓ 负载 = m_ack_t(status=nid);
|
||||
* - MSG_NOTIFY_DISMISS(0x0022) ↑ 负载 = uint32 nid。
|
||||
* - MSG_NOTIFY_DISMISS(0x0022) ↑ 负载 = uint32 nid;
|
||||
* - MSG_NOTIFY_PROGRESS(0x0024) ↑ 负载 = m_notify_progress_t(nid+progress,实时进度仅内存)。
|
||||
*
|
||||
* 设计要点:
|
||||
* - 只做「一次性 connect + send + read ACK」,不维护连接/订阅循环(与 meow_ipc.c 客户端同型);
|
||||
* - 映射层(SDK 枚举 ↔ IPC 字段)集中在本文件:分类枚举 CAT_* ↔ 字符串
|
||||
* "general"/"message"/"email"/"event"/"progress"/"media";timeout_ms → expire_timeout:
|
||||
* >0 该毫秒、0=不自动过期、-1(ONGOING)=0xFFFFFFFF(并置 ongoing=1);媒体类型置 media=1;
|
||||
* SDK `icon` → app_icon(空则 launcher 按 app_id 回退 app 图标);urgency 0-3 直通(越界钳位 NORMAL);
|
||||
* - 优雅降级:无 socket(connect 失败)/写失败/ACK 超时(SO_RCVTIMEO)/非 ACK 应答 →
|
||||
* 返回 0(调用方 meow_ui_notify.c 保留本地 id 兜底),绝不崩;
|
||||
* - 线程安全:app_id 经 pthread_once 缓存;socket 路径每次调用读 env MEOW_IPC_SOCK 覆盖
|
||||
@@ -82,8 +84,8 @@ static uint32_t timeout_to_expire(int timeout_ms)
|
||||
return (uint32_t)timeout_ms; /* 0(NEVER)/ >0(毫秒) */
|
||||
}
|
||||
|
||||
/* 构建 IPC 负载 m_notify_t(app_icon/actions/hints v1 留空,M2b D-Bus 桥再填)。
|
||||
* 仅在持有调用者互斥之外、发送前调用(纯 CPU 拷贝,不阻塞)。 */
|
||||
/* 构建 IPC 负载 m_notify_t(app_icon<->SDK icon;urgency 0-3;actions/hints v1 留空,
|
||||
* M2b D-Bus 桥再填)。仅在持有调用者互斥之外、发送前调用(纯 CPU 拷贝,不阻塞)。 */
|
||||
static void build_m_notify(const meow_notify *n, uint32_t replaces_id, m_notify_t *mn)
|
||||
{
|
||||
memset(mn, 0, sizeof *mn);
|
||||
@@ -91,6 +93,7 @@ static void build_m_notify(const meow_notify *n, uint32_t replaces_id, m_notify_
|
||||
snprintf(mn->category, sizeof mn->category, "%s", cat_to_str(n->cat));
|
||||
snprintf(mn->summary, sizeof mn->summary, "%s", n->title ? n->title : "");
|
||||
snprintf(mn->body, sizeof mn->body, "%s", n->body ? n->body : "");
|
||||
snprintf(mn->app_icon, sizeof mn->app_icon, "%s", n->icon ? n->icon : "");
|
||||
snprintf(mn->target_activity, sizeof mn->target_activity, "%s",
|
||||
n->target_activity ? n->target_activity : "");
|
||||
mn->replaces_id = replaces_id; /* 0=新建;>0=更新(不存在则落为新建,见 launcher) */
|
||||
@@ -98,6 +101,9 @@ static void build_m_notify(const meow_notify *n, uint32_t replaces_id, m_notify_
|
||||
mn->progress = (n->progress < -1) ? -1 : (n->progress > 100 ? 100 : n->progress);
|
||||
mn->media = (n->cat == MEOW_NOTIFY_CAT_MEDIA) ? 1 : 0;
|
||||
mn->ongoing = (n->timeout_ms == MEOW_NOTIFY_TIMEOUT_ONGOING) ? 1 : 0;
|
||||
/* urgency:越界钳位到 NORMAL(缺省);0-3 直通(launcher 侧再回退缺省) */
|
||||
mn->urgency = ((int)n->urgency >= 0 && (int)n->urgency < (int)MEOW_NOTIFY_URG_COUNT)
|
||||
? (uint8_t)n->urgency : (uint8_t)MEOW_NOTIFY_URG_NORMAL;
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
@@ -241,3 +247,36 @@ void meow_notify_ipc_dismiss(uint32_t nid)
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void meow_notify_ipc_update_progress(uint32_t nid, int progress)
|
||||
{
|
||||
int fd;
|
||||
if (nid == 0) return;
|
||||
m_notify_progress_t p;
|
||||
memset(&p, 0, sizeof p);
|
||||
p.nid = nid;
|
||||
p.progress = (progress < -1) ? -1 : (progress > 100 ? 100 : progress);
|
||||
fd = conn_path(ipc_sock_path());
|
||||
if (fd < 0) return; /* 无 socket:静默 */
|
||||
set_ack_timeout(fd);
|
||||
if (!send_frame(fd, MSG_NOTIFY_PROGRESS, 0x4E4F5450u /* "NOTP" */, &p, (uint32_t)sizeof p)) {
|
||||
close(fd); /* 写失败:静默 */
|
||||
return;
|
||||
}
|
||||
/* 读回应答(launcher 对 PROGRESS 回 MSG_ACK,best-effort;读回确保 launcher 已处理完) */
|
||||
uint8_t rhdr[MEOW_IPC_HDR_LEN];
|
||||
if (read_all(fd, rhdr, sizeof rhdr)) {
|
||||
uint32_t rmagic, rlen;
|
||||
uint16_t rver, rtype;
|
||||
memcpy(&rmagic, rhdr + 0, 4);
|
||||
memcpy(&rver, rhdr + 4, 2);
|
||||
memcpy(&rtype, rhdr + 6, 2);
|
||||
memcpy(&rlen, rhdr + 12, 4);
|
||||
if (rmagic == MEOW_IPC_MAGIC && rver == MEOW_IPC_VERSION &&
|
||||
rtype == MSG_ACK && rlen >= sizeof(m_ack_t)) {
|
||||
uint8_t pay[sizeof(m_ack_t)];
|
||||
(void)read_all(fd, pay, sizeof(m_ack_t)); /* 读到即确认;内容不关心 */
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
+7
-2
@@ -4,9 +4,10 @@
|
||||
* 定位(任务 #5 SDK↔IPC 桥关键断点):让框架 app 调 meow_notify_send() 的通知真正经
|
||||
* AF_UNIX IPC 送到 launcher(meow_launcherd)中央存储(meow_notif.c 的 meow_notif_post),
|
||||
* 通知中心(阶段 B · M5)才能显示。消息通道(FRAMEWORK_DESIGN §1 / meow_ipc.h):
|
||||
* - MSG_NOTIFY 0x0020 ↑:推送/更新通知(负载 m_notify_t);
|
||||
* - MSG_NOTIFY 0x0020 ↑:推送/更新通知(负载 m_notify_t;含 SDK icon→app_icon、urgency);
|
||||
* - MSG_NOTIFY_ACK 0x0021 ↓:落库结果(m_ack_t,status=launcher 分配的通知 id nid);
|
||||
* - MSG_NOTIFY_DISMISS 0x0022 ↑:撤下通知(负载 uint32 nid)。
|
||||
* - MSG_NOTIFY_DISMISS 0x0022 ↑:撤下通知(负载 uint32 nid);
|
||||
* - MSG_NOTIFY_PROGRESS 0x0024 ↑:实时更新通知进度(负载 m_notify_progress_t,仅改内存活跃槽)。
|
||||
*
|
||||
* 约定:只做「一次性发送 + 读 ACK」,不造 IPC 订阅循环;SDK 本地活动表(meow_ui_notify.c)
|
||||
* 保留(app 进程内即时查询/配额自检),真正的通知中心数据在 launcher 中央存储,二者以
|
||||
@@ -38,6 +39,10 @@ uint32_t meow_notify_ipc_send(const meow_notify *n, uint32_t replaces_id);
|
||||
* 静默(不崩、不回读 ACK)。 */
|
||||
void meow_notify_ipc_dismiss(uint32_t nid);
|
||||
|
||||
/* 一次性发送 MSG_NOTIFY_PROGRESS 更新 launcher 侧已存在通知的进度(仅改内存活跃槽,
|
||||
* 不落盘)。best-effort:写失败/无 socket 静默。 */
|
||||
void meow_notify_ipc_update_progress(uint32_t nid, int progress);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -297,12 +297,13 @@ typedef enum {
|
||||
} meow_notify_urgency;
|
||||
|
||||
/* 发送负载(对齐 freedesktop Notify() 字段;SDK 内部复制副本,不持 app 外部指针,
|
||||
* app 只需保证 title/body/target_activity 指针在调用返回前有效)。 */
|
||||
* app 只需保证 icon/title/body/target_activity 指针在调用返回前有效)。 */
|
||||
typedef struct meow_notify {
|
||||
meow_notify_category cat; /* 类型(未声明则按 4 种上限自动注册) */
|
||||
meow_notify_urgency urgency; /* 紧急度 */
|
||||
meow_notify_urgency urgency; /* 紧急度(缺省 MEOW_NOTIFY_URG_NORMAL;越界钳位) */
|
||||
const char *title; /* summary:标题,单行(必填,NULL 则发送失败) */
|
||||
const char *body; /* body:正文,可多行(可 NULL) */
|
||||
const char *icon; /* app_icon:图标 icon name 或 path;NULL/空 = 用该 app 默认图标(launcher 按 app_id 回退) */
|
||||
int timeout_ms; /* 见上超时语义;推荐 MEOW_NOTIFY_TIMEOUT_* */
|
||||
const char *target_activity; /* 通知中心点击跳转的 Activity 名(可 NULL;M3 导航预留) */
|
||||
int progress; /* 进度 0-100;-1=不显示进度条(缺省 -1) */
|
||||
@@ -318,6 +319,11 @@ uint32_t meow_notify_send(const meow_notify *n);
|
||||
/* 取消一条通知。1=成功;0=未找到(id 无效/已过期/已取消)。 */
|
||||
int meow_notify_cancel(uint32_t id);
|
||||
|
||||
/* 实时更新一条活动通知的进度(0-100,-1=清除进度条)。local_id=meow_notify_send 的返回值。
|
||||
* 语义(用户定案):仅改 SDK 内部活动槽 + 经 IPC 通知 launcher 改**内存活跃槽**;不落盘——
|
||||
* TF 快照只在「创建时 / 结束(100% 或 dismiss)」触发。返回 1=找到并更新;0=未找到/非法。 */
|
||||
int meow_notify_update_progress(uint32_t local_id, int progress);
|
||||
|
||||
/* 查询当前活动(未过期、未取消)通知数/是否还有。 */
|
||||
int meow_notify_active_count(void);
|
||||
int meow_notify_count_in_type(meow_notify_category cat);
|
||||
|
||||
+19
-13
@@ -67,8 +67,9 @@ static char *g_dump_path = NULL;
|
||||
* g_sbar_collapsed = 目标态(1=上收);g_sbar_collapse_h = 当前实际上收偏移
|
||||
* (0..MUI_SBAR_H:0=完全展开,MUI_SBAR_H=内容全部上移出屏、仅留提示线)。
|
||||
* 基座让 meow_ui_statusbar_set_collapsed(on) 立即生效(true→只画提示线/内容上移);
|
||||
* 过渡(每帧插值)留待后续代理或经 meow_ui_statusbar_animate(ms) 启用的简易线性逼近。 */
|
||||
#define MUI_SBAR_HINT_H 6 /* 上收状态下顶部提示线高(px) */
|
||||
* 过渡(每帧插值)留待后续代理或经 meow_ui_statusbar_animate(ms) 启用的简易线性逼近。
|
||||
* 「收合=只留提示线」占高 = MUI_SBAR_COLLAPSE_H(=MEOW_SBAR_HOTZONE_FS=4,meow_ui_sys.h),
|
||||
* 与 inset(meow_ui_statusbar_height())/顶部下滑热区/收合渲染同口径——replaced MUI_SBAR_HINT_H。 */
|
||||
static int g_sbar_collapsed = 0; /* 目标:1=上收 */
|
||||
static int g_sbar_collapse_h = 0; /* 当前上收偏移(0..MUI_SBAR_H) */
|
||||
static int g_sbar_collapse_anim_ms = 0; /* 过渡时长(0=瞬切);meow_ui_statusbar_animate 设置 */
|
||||
@@ -357,7 +358,8 @@ void meow_ui_swipe_hint(int x)
|
||||
if (!g_init_ok) return;
|
||||
const meow_theme *th = meow_theme_get();
|
||||
/* 进度条画在状态栏下沿(z 在状态栏之下,不被全局状态栏覆盖)。
|
||||
* 有状态栏(非全屏)→ y = 状态栏高度;无状态栏(全屏/隐藏)→ y=0。 */
|
||||
* 有状态栏(非全屏)→ y = 状态栏高度;收合(collapsed)→ y=提示线下缘
|
||||
* (MUI_SBAR_COLLAPSE_H,与提示线不重叠);无状态栏(全屏/隐藏)→ y=0。 */
|
||||
int hy = meow_ui_statusbar_height();
|
||||
if (x > 0) {
|
||||
if (x > g_xres) x = g_xres;
|
||||
@@ -544,15 +546,16 @@ static int statusbar_collapse_in_transition(void)
|
||||
|
||||
/* 上收状态栏:内容整体上移出屏(不画时钟/电量),仅在顶部画一条「提示线」。
|
||||
* 与 meow_ui_swipe_hint(左滑返回进度条,5px,动态)不同:此线是「状态栏可下拉还原」的
|
||||
* 常驻提示(主题强调色下边缘)。原状态栏整块清回主题背景,避免残影(app inset 之内)。 */
|
||||
* 常驻提示(主题强调色下边缘)。收合只占/清「提示线」高度区域(MUI_SBAR_COLLAPSE_H=4),
|
||||
* 不再清整 MUI_SBAR_H(28) 行 —— app 内容按 inset=提示线高可上移到提示线下缘,无 28px 空条。 */
|
||||
static void statusbar_collapsed_render(int h)
|
||||
{
|
||||
(void)h;
|
||||
const meow_theme *th = meow_theme_get();
|
||||
int w = meow_ui_width();
|
||||
/* h 越大内容越贴顶;基座:折叠态整块清底 + 顶部提示线(提示线下缘=主题 accent) */
|
||||
meow_ui_fill_rect(0, 0, w, MUI_SBAR_H, th->bg);
|
||||
meow_ui_fill_rect(0, MUI_SBAR_HINT_H - 1, w, 1, th->accent);
|
||||
/* h 越大内容越贴顶;基座:折叠态清「提示线」区域底 + 顶部提示线(提示线下缘=主题 accent) */
|
||||
meow_ui_fill_rect(0, 0, w, MUI_SBAR_COLLAPSE_H, th->bg);
|
||||
meow_ui_fill_rect(0, MUI_SBAR_COLLAPSE_H - 1, w, 1, th->accent);
|
||||
}
|
||||
|
||||
/* ---- 公共 API(基座实现;动画插值骨架见 statusbar_collapse_step)---- */
|
||||
@@ -576,9 +579,10 @@ void meow_ui_statusbar_animate(int ms)
|
||||
int meow_ui_statusbar_hotzone(void)
|
||||
{
|
||||
/* 非全屏=整条状态栏可视;全屏时缩小到 MEOW_SBAR_HOTZONE_FS(保留一处下拉入口)。
|
||||
* 上收(collapsed、非全屏)时热区=提示线下缘高度。全屏态由 meow_ui_sys 维护。 */
|
||||
* 上收(collapsed、非全屏)时热区=提示线下缘高度(MUI_SBAR_COLLAPSE_H,与渲染/inset 同口径)。
|
||||
* 全屏态由 meow_ui_sys 维护。 */
|
||||
if (meow_ui_sys_statusbar_active())
|
||||
return g_sbar_collapsed ? MUI_SBAR_HINT_H : MUI_SBAR_H;
|
||||
return g_sbar_collapsed ? MUI_SBAR_COLLAPSE_H : MUI_SBAR_H;
|
||||
return MEOW_SBAR_HOTZONE_FS;
|
||||
}
|
||||
|
||||
@@ -602,10 +606,12 @@ static void present(void)
|
||||
if (!g_refresh_always_max) {
|
||||
if (g_last_present_ms && now - g_last_present_ms < (unsigned long long)period) return;
|
||||
}
|
||||
/* 全局状态栏(A-0)+ 上收(collapsed)基座:上屏前把状态栏画进 back_buf 顶部 MUI_SBAR_H 行。
|
||||
* 全屏/隐藏时 active()==0 不画(沉浸),app 内容可占满整屏。触发条件:
|
||||
* 数据已变(1s 轻刷/显隐切换) / 顶条被 app 内容触及 / 上收动画未到位(逐帧推进)。
|
||||
* 展开态仍走 meow_ui_sys_statusbar_render()(meow_ui_sys.c 不改,留给后续代理);
|
||||
/* 全局状态栏(A-0)+ 上收(collapsed)基座:上屏前把状态栏画进 back_buf 顶部行。
|
||||
* 展开态=整条(MUI_SBAR_H 行);收合态只占/清「提示线」区域(MUI_SBAR_COLLAPSE_H 行),
|
||||
* app 内容(inset=提示线高)可上移到提示线下缘,无 28px 空条。全屏/隐藏时 active()==0
|
||||
* 不画(沉浸),app 内容可占满整屏。触发条件:数据已变(1s 轻刷/显隐切换) /
|
||||
* 顶条被 app 内容触及 / 上收动画未到位(逐帧推进)。展开态仍走
|
||||
* meow_ui_sys_statusbar_render()(meow_ui_sys.c 不改,留给后续代理);
|
||||
* 上收折叠态(collapse_h>=MUI_SBAR_H)由基座只画提示线(内容上移出屏)。 */
|
||||
if (meow_ui_sys_statusbar_active() &&
|
||||
(meow_ui_sys_statusbar_force() || statusbar_touched() ||
|
||||
|
||||
+6
-2
@@ -317,8 +317,12 @@ void meow_ui_run(const meow_ui_events *ev)
|
||||
if (in_startup) continue; /* 启动窗口进度条静音 */
|
||||
int x0 = e.a, xc = e.b, dx = xc - x0; /* dx=当前X-按下X */
|
||||
/* SDK 自动画顶部条:长度=手指当前 X(=距左缘距离,向内划长度随位移增长)。
|
||||
* 全屏/沉浸不画系统条(无返回手势);APP 若注册 on_swipe_progress 仍可自绘。 */
|
||||
if (meow_ui_sys_statusbar_active()) meow_ui_swipe_hint(xc);
|
||||
* M2.5x/A-13:全屏/收合下「左缘返回手势保留」,顶部动态提示条(meow_ui_swipe_hint)
|
||||
* 仍需绘制——不再以 meow_ui_sys_statusbar_active()(全屏/隐藏=0)开关,否则全屏
|
||||
* 时滑条完全不显示。条位 y=meow_ui_statusbar_height():非全屏=状态栏下沿、
|
||||
* 全屏=0、收合=提示线下缘(MUI_SBAR_COLLAPSE_H),与提示线不重叠加。
|
||||
* APP 若注册 on_swipe_progress 仍可自绘(系统条照常画)。 */
|
||||
meow_ui_swipe_hint(xc);
|
||||
if (g_events_set && g_events.on_swipe_progress)
|
||||
g_events.on_swipe_progress(x0, dx);
|
||||
meow_ui_flush_region(0, meow_ui_statusbar_height(), meow_ui_width(), 6);
|
||||
|
||||
+28
-1
@@ -35,7 +35,10 @@
|
||||
/* ---- 内部活动表尺寸(配额见 meow_ui.h) ---- */
|
||||
#define MEOW_NOTIFY_MAX_ACTIVE (MEOW_NOTIFY_MAX_TYPES * MEOW_NOTIFY_MAX_PER_TYPE)
|
||||
|
||||
/* 活动通知槽(内部;标题/正文等复制副本,不持 app 外部指针,避免栈字符串悬垂) */
|
||||
/* 活动槽内 icon 缓冲上限(与 IPC app_icon[48] 一致;SDK 复制副本,不持 app 外部指针) */
|
||||
#define MEOW_SLOT_ICON_MAX 48
|
||||
|
||||
/* 活动通知槽(内部;标题/正文/图标等复制副本,不持 app 外部指针,避免栈字符串悬垂) */
|
||||
typedef struct {
|
||||
uint32_t id; /* 本地唯一 id(app 侧句柄);0=空闲槽 */
|
||||
uint32_t ipc_id; /* launcher 中央存储分配的通知 id(nid);0=未同步/降级 */
|
||||
@@ -47,6 +50,7 @@ typedef struct {
|
||||
char title[64];
|
||||
char body[128];
|
||||
char target_activity[32];
|
||||
char icon[MEOW_SLOT_ICON_MAX]; /* 图标 name/path;空=用 app 默认图标(launcher 回退) */
|
||||
int progress; /* 0-100;-1=无进度条 */
|
||||
} notify_slot_t;
|
||||
|
||||
@@ -111,6 +115,7 @@ static void notify_fill(notify_slot_t *s, const meow_notify *n, uint32_t id, uin
|
||||
snprintf(s->body, sizeof s->body, "%s", n->body ? n->body : "");
|
||||
snprintf(s->target_activity, sizeof s->target_activity, "%s",
|
||||
n->target_activity ? n->target_activity : "");
|
||||
snprintf(s->icon, sizeof s->icon, "%s", n->icon ? n->icon : "");
|
||||
s->progress = (n->progress < -1) ? -1 : (n->progress > 100 ? 100 : n->progress);
|
||||
}
|
||||
|
||||
@@ -253,6 +258,28 @@ int meow_notify_cancel(uint32_t id)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int meow_notify_update_progress(uint32_t local_id, int progress)
|
||||
{
|
||||
int p, i, found = 0;
|
||||
uint32_t ipc_id = 0;
|
||||
if (local_id == 0) return 0;
|
||||
p = (progress < -1) ? -1 : (progress > 100 ? 100 : progress); /* 钳位 [-1,100] */
|
||||
pthread_mutex_lock(&g_mu);
|
||||
notify_purge_expired();
|
||||
for (i = 0; i < MEOW_NOTIFY_MAX_ACTIVE; i++) {
|
||||
if (g_slots[i].active && g_slots[i].id == local_id) {
|
||||
g_slots[i].progress = p; /* 实时:仅改内存活动槽,不落盘 */
|
||||
ipc_id = g_slots[i].ipc_id; /* launcher 侧 nid;0=未同步/降级 */
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&g_mu);
|
||||
/* 落点(best-effort):经 IPC 通知 launcher 改其内存活跃槽;无 launcher/未同步则静默。 */
|
||||
if (found && ipc_id) meow_notify_ipc_update_progress(ipc_id, p);
|
||||
return found;
|
||||
}
|
||||
|
||||
int meow_notify_active_count(void)
|
||||
{
|
||||
int i, n = 0;
|
||||
|
||||
@@ -41,7 +41,7 @@ uint64_t meow_ui_time_ms(void)
|
||||
|
||||
/* ---- stub server 捕获(每次连接一帧) ---- */
|
||||
#define MAXCAP 16
|
||||
typedef struct { int type; m_notify_t n; uint32_t dismiss_id; uint32_t nid; } srec_t;
|
||||
typedef struct { int type; m_notify_t n; m_notify_progress_t prog; uint32_t dismiss_id; uint32_t nid; } srec_t;
|
||||
static srec_t g_rec[MAXCAP];
|
||||
static int g_nrec = 0;
|
||||
static int g_stop = 0;
|
||||
@@ -77,6 +77,7 @@ static void *server(void *arg)
|
||||
memset(&g_rec[idx], 0, sizeof g_rec[idx]);
|
||||
g_rec[idx].type = (int)type;
|
||||
if (type == MSG_NOTIFY && len >= sizeof(m_notify_t)) memcpy(&g_rec[idx].n, pay, sizeof(m_notify_t));
|
||||
if (type == MSG_NOTIFY_PROGRESS && len >= sizeof(m_notify_progress_t)) memcpy(&g_rec[idx].prog, pay, sizeof(m_notify_progress_t));
|
||||
if (type == MSG_NOTIFY_DISMISS && len >= 4) memcpy(&g_rec[idx].dismiss_id, pay, 4);
|
||||
/* 分配 nid = 100 + NOTIFY 序号 */
|
||||
uint32_t seq = 0;
|
||||
@@ -85,7 +86,7 @@ static void *server(void *arg)
|
||||
uint32_t ack_nid = g_rec[idx].nid;
|
||||
pthread_mutex_unlock(&g_mu);
|
||||
|
||||
if (type == MSG_NOTIFY || type == MSG_NOTIFY_DISMISS) {
|
||||
if (type == MSG_NOTIFY || type == MSG_NOTIFY_DISMISS || type == MSG_NOTIFY_PROGRESS) {
|
||||
m_ack_t a; memset(&a, 0, sizeof a); a.code = MEOW_OK; a.status = ack_nid;
|
||||
uint8_t rhdr[MEOW_IPC_HDR_LEN];
|
||||
uint32_t mag = MEOW_IPC_MAGIC; uint16_t ver = MEOW_IPC_VERSION, t = (uint16_t)
|
||||
@@ -140,11 +141,13 @@ int main(void)
|
||||
/* S1 通用通知 */
|
||||
meow_notify nt; memset(&nt, 0, sizeof nt);
|
||||
nt.cat = MEOW_NOTIFY_CAT_GENERAL; nt.urgency = MEOW_NOTIFY_URG_NORMAL;
|
||||
nt.title = "t1"; nt.timeout_ms = 0;
|
||||
nt.title = "t1"; nt.timeout_ms = 0; nt.icon = "os.meow.hello/icon.png";
|
||||
uint32_t id1 = meow_notify_send(&nt);
|
||||
check("S1 send 返回本地 id=1", id1 == 1);
|
||||
check("S1 active_count=1", meow_notify_active_count() == 1);
|
||||
check("S1 stub 回 nid=101", rec_at(0).nid == 101);
|
||||
check("S1 映射 urgency=NORMAL(1)", rec_at(0).n.urgency == MEOW_NOTIFY_URG_NORMAL);
|
||||
check("S1 映射 icon→app_icon", !strcmp(rec_at(0).n.app_icon, "os.meow.hello/icon.png"));
|
||||
|
||||
/* S2 媒体通知:单例 + media=1 */
|
||||
memset(&nt, 0, sizeof nt);
|
||||
@@ -182,6 +185,25 @@ int main(void)
|
||||
触发丢最旧的是 S5 循环第 4 次 send = 第 7 条 NOTIFY(rec[7]),其 replaces_id==103。 */
|
||||
check("S5 丢最旧后 send replaces_id=被丢nid(103)", rec_at(7).n.replaces_id == 103);
|
||||
|
||||
/* S5b update_progress:新发一条 progress → 本地 id → update → stub 捕获 MSG_NOTIFY_PROGRESS */
|
||||
memset(&nt, 0, sizeof nt);
|
||||
nt.cat = MEOW_NOTIFY_CAT_PROGRESS; nt.title = "prog"; nt.timeout_ms = 0;
|
||||
nt.progress = 10;
|
||||
uint32_t idp = meow_notify_send(&nt);
|
||||
int ni = -1;
|
||||
for (int i = 0; i < MAXCAP; i++) {
|
||||
srec_t r = rec_at(i);
|
||||
if (r.type == MSG_NOTIFY && !strcmp(r.n.summary, "prog")) { ni = i; break; }
|
||||
}
|
||||
check("S5b 找到 prog 通知帧", ni >= 0);
|
||||
int rc_up = meow_notify_update_progress(idp, 70);
|
||||
check("S5b update_progress 返回 1", rc_up == 1);
|
||||
srec_t pr = rec_at(ni + 1);
|
||||
check("S5b stub 捕获 MSG_NOTIFY_PROGRESS 帧", pr.type == MSG_NOTIFY_PROGRESS);
|
||||
check("S5b progress nid=该通知 launcher nid", ni >= 0 && pr.prog.nid == rec_at(ni).nid);
|
||||
check("S5b progress 载=70", pr.prog.progress == 70);
|
||||
check("S5b update_progress(未知 id) 返回 0", meow_notify_update_progress(0xFFFFFF, 50) == 0);
|
||||
|
||||
stop_server();
|
||||
pthread_join(th, NULL);
|
||||
|
||||
|
||||
+22
-2
@@ -30,6 +30,7 @@
|
||||
typedef struct {
|
||||
uint32_t type; /* 收到的帧类型 */
|
||||
m_notify_t n; /* MSG_NOTIFY 负载 */
|
||||
m_notify_progress_t prog; /* MSG_NOTIFY_PROGRESS 负载 */
|
||||
uint32_t dismiss_id; /* MSG_NOTIFY_DISMISS 负载 */
|
||||
uint32_t req_id;
|
||||
uint32_t nid_to_return; /* ACK 中回填的 status */
|
||||
@@ -47,6 +48,7 @@ static void cap_store(uint32_t type, uint32_t req_id, const uint8_t *pay, uint32
|
||||
g_cap.req_id = req_id;
|
||||
g_cap.nid_to_return = nid_to_return;
|
||||
if (type == MSG_NOTIFY && len >= sizeof(m_notify_t)) memcpy(&g_cap.n, pay, sizeof(m_notify_t));
|
||||
if (type == MSG_NOTIFY_PROGRESS && len >= sizeof(m_notify_progress_t)) memcpy(&g_cap.prog, pay, sizeof(m_notify_progress_t));
|
||||
if (type == MSG_NOTIFY_DISMISS && len >= 4) memcpy(&g_cap.dismiss_id, pay, 4);
|
||||
g_cap.got = 1;
|
||||
pthread_mutex_unlock(&g_cap_mu);
|
||||
@@ -87,7 +89,7 @@ static void *server_thread(void *arg)
|
||||
|
||||
/* MSG_NOTIFY → 回 m_ack_t(code=OK, status=nid_to_return);
|
||||
* MSG_NOTIFY_DISMISS → 回 m_ack_t(code=OK, status=0,同 launcher 行为)。 */
|
||||
if (type == MSG_NOTIFY || type == MSG_NOTIFY_DISMISS) {
|
||||
if (type == MSG_NOTIFY || type == MSG_NOTIFY_DISMISS || type == MSG_NOTIFY_PROGRESS) {
|
||||
m_ack_t a;
|
||||
memset(&a, 0, sizeof a);
|
||||
a.code = MEOW_OK;
|
||||
@@ -152,9 +154,10 @@ int main(void)
|
||||
meow_notify nt;
|
||||
memset(&nt, 0, sizeof nt);
|
||||
nt.cat = MEOW_NOTIFY_CAT_PROGRESS;
|
||||
nt.urgency = MEOW_NOTIFY_URG_NORMAL;
|
||||
nt.urgency = MEOW_NOTIFY_URG_HIGH;
|
||||
nt.title = "下载中";
|
||||
nt.body = "70%";
|
||||
nt.icon = "os.meow.hello/icon.png";
|
||||
nt.timeout_ms = 5000; /* >0 → expire=5000, ongoing=0 */
|
||||
nt.progress = 150; /* 钳位 → 100 */
|
||||
uint32_t nid = meow_notify_ipc_send(&nt, 0);
|
||||
@@ -175,6 +178,8 @@ int main(void)
|
||||
check("T2 replaces_id 透传=0", cn->replaces_id == 0);
|
||||
check("T1 app_id=testapp", !strcmp(cn->app_id, "testapp"));
|
||||
check("T1 summary=下载中", !strcmp(cn->summary, "下载中"));
|
||||
check("T1 urgency(HIGH)→wire urgency=2", cn->urgency == MEOW_NOTIFY_URG_HIGH);
|
||||
check("T1 icon→app_icon", !strcmp(cn->app_icon, "os.meow.hello/icon.png"));
|
||||
}
|
||||
|
||||
/* ---------- T1/T2:媒体类型 + ONGOING(-1) ---------- */
|
||||
@@ -275,6 +280,21 @@ int main(void)
|
||||
check("T5 dismiss 负载=nid=0xABCD", g_cap.dismiss_id == 0xABCDu);
|
||||
}
|
||||
|
||||
/* ---------- T6:update_progress 发 MSG_NOTIFY_PROGRESS(nid + progress 钳位)---------- */
|
||||
{
|
||||
char sock[108];
|
||||
g_listen_fd = arb_listen(sock, sizeof sock);
|
||||
setenv("MEOW_IPC_SOCK", sock, 1);
|
||||
pthread_t th;
|
||||
pthread_create(&th, NULL, server_thread, NULL);
|
||||
meow_notify_ipc_update_progress(0x1234, 250); /* 钳位 250→100 */
|
||||
pthread_join(th, NULL);
|
||||
close(g_listen_fd);
|
||||
check("T6 stub 收到 MSG_NOTIFY_PROGRESS 帧", g_cap.got && g_cap.type == MSG_NOTIFY_PROGRESS);
|
||||
check("T6 progress 负载 nid=0x1234", g_cap.prog.nid == 0x1234);
|
||||
check("T6 progress 钳位 250→100", g_cap.prog.progress == 100);
|
||||
}
|
||||
|
||||
printf("\n%s (%d failure%s)\n", failures ? "RESULT: FAIL" : "RESULT: PASS",
|
||||
failures, failures == 1 ? "" : "s");
|
||||
return failures ? 1 : 0;
|
||||
|
||||
+19
-1
@@ -49,6 +49,7 @@ static void launcher_map(const m_notify_t *mn, meow_notif_t *n)
|
||||
snprintf(n->target_activity, sizeof n->target_activity, "%s", mn->target_activity);
|
||||
n->expire_timeout = mn->expire_timeout;
|
||||
n->progress = mn->progress;
|
||||
n->urgency = mn->urgency; /* 0-3;旧调用=0 → LOW(静默) */
|
||||
n->ongoing = mn->ongoing;
|
||||
n->media = mn->media;
|
||||
}
|
||||
@@ -59,6 +60,15 @@ static void launcher_map(const m_notify_t *mn, meow_notif_t *n)
|
||||
static int g_listen_fd = -1;
|
||||
static int g_stop = 0;
|
||||
static uint32_t g_posted_nid = 0;
|
||||
static meow_notif_t g_stored; /* 回读 launcher 存储的最近一条通知(store_cb) */
|
||||
static int g_store_called = 0;
|
||||
|
||||
static int store_cb(const meow_notif_t *n, void *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if (n) { g_stored = *n; g_store_called = 1; }
|
||||
return 1; /* 只取第一条 */
|
||||
}
|
||||
|
||||
static void reply_ack(int c, uint16_t type, uint32_t req_id, uint32_t status)
|
||||
{
|
||||
@@ -130,13 +140,21 @@ int main(void)
|
||||
|
||||
/* SDK send → launcher 真存储。media + ONGOING 走全部映射分支。 */
|
||||
meow_notify nt; memset(&nt, 0, sizeof nt);
|
||||
nt.cat = MEOW_NOTIFY_CAT_MEDIA; nt.urgency = MEOW_NOTIFY_URG_NORMAL;
|
||||
nt.cat = MEOW_NOTIFY_CAT_MEDIA; nt.urgency = MEOW_NOTIFY_URG_HIGH;
|
||||
nt.title = "正在播放"; nt.timeout_ms = -1; nt.progress = 40;
|
||||
nt.icon = "os.meow.hello/icon.png";
|
||||
uint32_t nid = meow_notify_ipc_send(&nt, 0);
|
||||
check("send 经 launcher 真存储回 nid>0", nid != 0);
|
||||
check("send 拿到 launcher 分配的 nid(与 post 一致)", g_posted_nid == nid);
|
||||
check("launcher 存储 count(media app)=1", meow_notif_count("intgapp") == 1);
|
||||
|
||||
/* 回读 launcher 存储,验证 urgency/icon/progress 全链路落库 */
|
||||
g_store_called = 0; memset(&g_stored, 0, sizeof g_stored);
|
||||
meow_notif_list(NULL, store_cb, NULL);
|
||||
check("post 存储 urgency=HIGH(2)", g_store_called && g_stored.urgency == MEOW_NOTIFY_URG_HIGH);
|
||||
check("post 存储 icon→app_icon", g_stored.app_icon[0] && !strcmp(g_stored.app_icon, "os.meow.hello/icon.png"));
|
||||
check("post 存储 progress=40", g_stored.progress == 40);
|
||||
|
||||
/* SDK dismiss → launcher 撤下 */
|
||||
meow_notify_ipc_dismiss(nid);
|
||||
check("dismiss 后 launcher 存储 count=0", meow_notif_count("intgapp") == 0);
|
||||
|
||||
Reference in new issue
Block a user