/* meow_ui_nav.c — App 侧 M3 导航上报封装(SDK 公共件;见 meow_ui_nav.h)。 * * 只做「组装 m_nav_t + 经 meow_notify_ipc 一次性发送 MSG_NAV」,不维护连接/订阅循环; * launcher 主循环单写者消费(回复 ACK)。全部失败路径优雅降级(无 socket/写失败/超时 * → 静默返回,不崩)。状态(栈深/顶层/app_id)仅进程内缓存,无并发写(App 页面线程调用)。 */ #include "meow_ui_nav.h" #include "meow_ipc.h" #include "meow_notify_ipc.h" /* meow_notify_ipc_send_raw(复用其一次性帧传输层) */ #include #include #include static char g_app_id[MEOW_APP_ID_MAX] = ""; static int g_depth = 0; static char g_top[MEOW_ACT_MAX] = ""; static int g_inited = 0; /* app_id:env MEOW_LOG_APP(与 meow_ui_log/meow_notify_ipc 取值口径一致),缺省 "app"。 */ static const char *nav_app_id(void) { if (!g_app_id[0]) { const char *s = getenv("MEOW_LOG_APP"); snprintf(g_app_id, sizeof g_app_id, "%s", (s && s[0]) ? s : "app"); } return g_app_id; } int meow_ui_nav_init(void) { if (g_inited) return g_depth; g_inited = 1; nav_app_id(); const char *chain = getenv("MEOW_CHAIN"); if (chain && chain[0]) { g_depth = 1; for (const char *p = chain; *p; p++) if (*p == ';') g_depth++; } const char *act = getenv("MEOW_ACTIVITY"); if (act && act[0]) snprintf(g_top, sizeof g_top, "%s", act); return g_depth; } int meow_ui_nav_depth(void) { meow_ui_nav_init(); return g_depth; } const char *meow_ui_nav_top(void) { meow_ui_nav_init(); return g_top; } void meow_ui_nav_report(uint32_t depth, const char *top) { meow_ui_nav_init(); m_nav_t n; memset(&n, 0, sizeof n); snprintf(n.app_id, sizeof n.app_id, "%s", nav_app_id()); n.nav_type = MEOW_NAV_REPORT; n.depth = depth; if (top) snprintf(n.current, sizeof n.current, "%s", top); (void)meow_notify_ipc_send_raw(MSG_NAV, &n, (uint32_t)sizeof n, 1); /* 进程内镜像:App 侧也维持当前栈深/顶层(跨 TU 只读用) */ g_depth = (int)depth; if (top) snprintf(g_top, sizeof g_top, "%s", top); } void meow_ui_nav_request_exit(void) { meow_ui_nav_init(); m_nav_t n; memset(&n, 0, sizeof n); snprintf(n.app_id, sizeof n.app_id, "%s", nav_app_id()); n.nav_type = MEOW_NAV_EXIT; n.depth = 0; (void)meow_notify_ipc_send_raw(MSG_NAV, &n, (uint32_t)sizeof n, 1); g_depth = 0; g_top[0] = 0; }