fix(launcher/amsd): amsd MSG_AMS_START 拉起缺口——pending-start 抽 meow_ams_start 模块复用启动链 + 负错误码符修复

根因(真机日志实证,M2.92 遗留):meow_ams_pending_start_set 误返回正错误码
(-MEOW_ERR_BUSY=+8/-MEOW_ERR_INVAL=+1),ipc_dispatch 的 rc<0?-rc:MEOW_OK 把「有前台 App
拒绝/空包名非法」误判为 OK(0) → amsd 报 OK 但 pending 未置位 → App 永不拉起(am start 报 OK
但界面没出现/进程未起)。

launcher:
- 新增自包含模块 meow_ams_start.c/.h(ops 注入 launch=launch_app/launch_activity、
  resolve=resolve_chain、log=logmsg):pending 状态 + 拉起决策 + picker 上下文。
- set 统一返回负 MEOW_ERR_*(根因修复);consume 复用既有启动链路真正拉起目标 App,
  列表未就绪(state!=0)保留 pending 待 2s 重扫重试,不再静默丢弃。
- main_menu run_menu 改经 meow_ams_start_consume 消费(保留 launch_fail_toast/菜单收尾);
  app_launcher 移除旧 g_ams_start/g_ams_pick_* 迁入模块;util meow_ipc_process 顶部同步 busy、
  meow_ipc_init 末尾 meow_ams_launcher_init()。
- build_launcher.sh 编入 meow_ams_start.c;meow_launcher_internal.h 更新挂点声明。

amsd(协议层归属说明):cmd_start 的 busy 判定对照 launcher ACK 正幅度(busy=8),
原 (uint32_t)MEOW_ERR_BUSY=0xFFFFFFF8 永不匹配 → busy 落入 launcher offline,改 (uint32_t)(-MEOW_ERR_BUSY)。

验证:宿主 test_ams_start.c 33 断言全 PASS(合法->拉起链、activity chain 透传、空包名/非法/busy
不拉起不崩、列表未就绪保留 pending、无路由 NO ROUTE、启动失败 idx 回报、picker 取回);
launcher 目录全量回归 test_media/bgplay/depends/notif_panel/notif_tf/settings_brightness/
vol_ramp_jack/host_icon + test_font_tier/weight 全 PASS;mipsel -Wall -Wextra 0 warning。
新 md5:meow_launcherd a8200ae1b0aa68d7262749db87377d49、meow_amsd 7ddc677ce7938bc9b95c83c17bc78295。(M2.98 待打包,未刷机)
This commit is contained in:
MeowOS committed 2026-09-01 19:40:29 +08:00
1 parent 7e7e45ae26
commit 980d161972
13 files changed
+446 -101

No files matched your search

+129
View File
@@ -0,0 +1,129 @@
/* meow_ams_start.c — MSG_AMS_START 拉起决策(AMSD_DESIGN §4.3)。
*
* 独立模块(无 launcher 内部依赖,仅 meow_ipc.h):持有 pending-start 状态 + 拉起决策,
* 经 ops 注入真实启动链路(launch_app/launch_activity + resolve_chain + logmsg),
* 使「am start」在 run_menu 主循环中真正拉起目标 App。
*
* 根因修复:历史实现 `meow_ams_pending_start_set` 返回 `-MEOW_ERR_BUSY`(=+8,正)而非
* 负错误码,ipc_dispatch 的 `rc<0?-rc:MEOW_OK` 因此把「有前台 App 拒绝」误判为 OK(0),
* 且拒绝发生在置 pending 之前 → amsd 报 OK 但 App 永不拉起。本模块统一为负 MEOW_ERR_*。
*
* 单一写者约定:pending 状态只在主循环上下文写入/消费(ipc_dispatch 写、run_menu 消费),
* 与 launcher 「单写者」纪律一致,无需锁。
*/
#include "meow_ams_start.h"
#include <stdio.h>
#include <string.h>
struct meow_ams_start_state {
char pkg[MEOW_APP_ID_MAX];
char act[MEOW_ACT_MAX];
int pending;
/* picker 上下文(二期;pick_armed=1 时 next launch 注入 env) */
char pick_action[24];
char pick_caller[MEOW_APP_ID_MAX];
uint32_t pick_req;
int pick_armed;
};
static struct meow_ams_start_state g_ams; /* 主循环单写者,无锁 */
static struct meow_ams_ops g_ops;
static int g_busy; /* =g_app_session_active 镜像(主循环每圈同步) */
void meow_ams_ops_init(const struct meow_ams_ops *ops)
{
if (ops) g_ops = *ops;
else memset(&g_ops, 0, sizeof g_ops);
}
void meow_ams_set_busy(int busy)
{
g_busy = busy;
}
int meow_ams_pending_start_set(const char *pkg, const char *act)
{
if (!pkg || !pkg[0]) return MEOW_ERR_INVAL; /* 负错误码(根因修复) */
if (g_busy) return MEOW_ERR_BUSY; /* 有前台 App:拒绝(负错误码) */
snprintf(g_ams.pkg, sizeof g_ams.pkg, "%s", pkg);
g_ams.act[0] = 0;
if (act && act[0]) snprintf(g_ams.act, sizeof g_ams.act, "%s", act);
g_ams.pending = 1;
return 0;
}
int meow_ams_pending_start_set_ex(const char *pkg, const char *act,
const char *pick_action, uint32_t pick_req,
const char *pick_caller)
{
int rc = meow_ams_pending_start_set(pkg, act);
if (rc != 0) return rc; /* 拒绝(有前台 App / 参数非法) */
g_ams.pick_action[0] = 0;
g_ams.pick_caller[0] = 0;
g_ams.pick_req = 0;
g_ams.pick_armed = 0;
if (pick_action && pick_action[0]) {
snprintf(g_ams.pick_action, sizeof g_ams.pick_action, "%s", pick_action);
if (pick_caller) snprintf(g_ams.pick_caller, sizeof g_ams.pick_caller, "%s", pick_caller);
g_ams.pick_req = pick_req;
g_ams.pick_armed = 1;
}
return 0;
}
int meow_ams_take_picker(char *action, int action_len,
char *caller, int caller_len, uint32_t *req)
{
if (!g_ams.pick_armed) return 0;
g_ams.pick_armed = 0;
if (action && action_len > 0) snprintf(action, action_len, "%s", g_ams.pick_action);
if (caller && caller_len > 0) snprintf(caller, caller_len, "%s", g_ams.pick_caller);
if (req) *req = g_ams.pick_req;
return 1;
}
int meow_ams_start_consume(const char *const *ids, int napps, int state,
char *toast, int toast_len, int *app_ran, int *idx_out)
{
if (app_ran) *app_ran = 0;
if (idx_out) *idx_out = -1;
if (!g_ams.pending || g_busy) return 0; /* 无待拉起 / 前台 App 会话中 */
if (state != 0) {
/* 应用列表未就绪:保留 pending(不丢「am start」),等 run_menu 2s 重扫后重试。 */
if (toast && toast_len > 0) snprintf(toast, toast_len, "AMS START: app list not ready");
return 2;
}
int idx = -1;
for (int i = 0; i < napps; i++)
if (ids[i] && !strcmp(ids[i], g_ams.pkg)) { idx = i; break; }
if (idx < 0) {
g_ams.pending = 0;
if (toast && toast_len > 0) snprintf(toast, toast_len, "AMS START: NO APP %s", g_ams.pkg);
return 1;
}
char chain[MEOW_CHAIN_MAX] = "";
if (g_ams.act[0]) {
int depth = 0;
int rc = g_ops.resolve ? g_ops.resolve(g_ams.pkg, g_ams.act, chain, &depth)
: MEOW_ERR_NOENT;
if (rc != MEOW_OK) {
g_ams.pending = 0;
if (toast && toast_len > 0)
snprintf(toast, toast_len, "AMS: NO ROUTE %s/%s", g_ams.pkg, g_ams.act);
return 1;
}
}
g_ams.pending = 0;
if (idx_out) *idx_out = idx;
/* 复用既有启动链路(launch_app/launch_activity 阻塞至 app 退出或 exec 失败)
* chain 空=裸启动;非空=经 resolve_chain 的 activity 链(含参透传)。
* 启动失败(lr<0)不在此设 toast:调用方经 idx_out 拿到 apps[idx].name 打 launch_fail_toast。 */
int lr = g_ops.launch ? g_ops.launch(idx, chain[0] ? chain : NULL) : -MEOW_ERR_INTERNAL;
if (app_ran) *app_ran = (lr == 0);
return 1;
}