Files
MeowOS-For-R3P2/patch_v2/meow_launcherd/meow_ams_start.c
T
MeowOS 980d161972 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 待打包,未刷机)
2026-09-01 19:40:29 +08:00

130 lines
5.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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;
}