feat(bt): 批①后台常驻框架实施 — meow_media_app_resident按app会话判活跃+should_keep三参(keepalive||bg_audio&&resident)+background_keepalive声明解析透传+amsd EV BG/FG上报;宿主test_media39/test_bgplay/test_bg_keep19全过,0warning;落盘APP_BACKGROUND_KEEPALIVE_P1;降配(nice)待真机未做
This commit is contained in:
1 parent
7e68313981
commit
f3ae06d7cd
10 files changed
+330
-30
No files matched your search
@@ -123,6 +123,24 @@ static void ams_report_exit(const struct app *a, int status, long long dur_ms)
|
||||
ams_report_exit_id(a->id, status, dur_ms);
|
||||
}
|
||||
|
||||
/* 批①后台常驻上报(单向 best-effort):转后台 `EV BG <app> <pid>`、回前台 `EV FG <app>`。
|
||||
* amsd 收到后置 AMS_BG/AMS_FG(批③后台管理页元数据来源);旧 launcher 不发、amsd 不识别也不崩。 */
|
||||
static void ams_report_bg(const char *app_id, pid_t pid)
|
||||
{
|
||||
if (!app_id || !app_id[0]) return;
|
||||
char line[256];
|
||||
int l = snprintf(line, sizeof line, "EV BG %s %d\n", app_id, (int)pid);
|
||||
if (l > 0) ams_send(line, l);
|
||||
}
|
||||
|
||||
static void ams_report_fg(const char *app_id)
|
||||
{
|
||||
if (!app_id || !app_id[0]) return;
|
||||
char line[256];
|
||||
int l = snprintf(line, sizeof line, "EV FG %s\n", app_id);
|
||||
if (l > 0) ams_send(line, l);
|
||||
}
|
||||
|
||||
/* ---- stdout/stderr 管道捕获(AMSD_DESIGN §5):前台 waitpid 循环排空 + 按行转发 ---- */
|
||||
static char g_ams_out_line[1024]; /* 未完结行缓冲(无 \n) */
|
||||
static int g_ams_out_n = 0;
|
||||
@@ -319,6 +337,7 @@ static void meow_acct_sync(const char *app_id, const struct app *ap)
|
||||
a->framework = ap->framework;
|
||||
a->background = ap->background; /* M4 */
|
||||
a->background_audio = ap->background_audio;
|
||||
a->background_keepalive = ap->background_keepalive; /* 批① */
|
||||
strncpy(a->icon, ap->icon, 128);
|
||||
app_name_copy(a->name, (int)sizeof a->name, ap->name);
|
||||
strncpy(a->exec, ap->exec, 128);
|
||||
@@ -648,6 +667,7 @@ void meow_parse_app_json(FILE *f, struct app *a)
|
||||
int fonts = 0, fonts_set = 0; /* app.json "fonts":<档>(0=默认4K常用 1=大字库GBK 2=Full;缺省 0) */
|
||||
int background = 0; /* M4:app.json background=true(可注册无头后台服务) */
|
||||
int bg_audio = 0; /* M4:app.json background_audio=true(播放中退出转后台保活) */
|
||||
int bg_keepalive = 0; /* 批①:app.json background_keepalive=true(进入后台即保活,不依赖媒体会话) */
|
||||
struct app tmp;
|
||||
memset(&tmp, 0, sizeof tmp);
|
||||
while (fgets(buf, sizeof buf, f)) {
|
||||
@@ -779,6 +799,17 @@ void meow_parse_app_json(FILE *f, struct app *a)
|
||||
bg_audio = 1;
|
||||
}
|
||||
}
|
||||
/* "background_keepalive":true(批①:进入后台即保活,不依赖媒体会话=通用常驻)。
|
||||
* 注意 "background_keepalive" 是 "background" 的前缀:若本行先命中上方 background 分支,
|
||||
* json_str(buf,"background") 读出的是 "_keepalive…" ≠ true → 自然留 0,无害;
|
||||
* json_str 键前缀独立性(util.c:544 ident_ch)保证 "background"/"background_audio" 独立匹配不受影响。 */
|
||||
if (!bg_keepalive && strstr(buf, "background_keepalive")) {
|
||||
char v[8] = "";
|
||||
if (json_str(buf, "background_keepalive", v, sizeof v) > 0) {
|
||||
if (!strcmp(v, "true") || !strcmp(v, "1") || !strcmp(v, "yes"))
|
||||
bg_keepalive = 1;
|
||||
}
|
||||
}
|
||||
/* service.<svc>=mode:restart:max:window_ms(M1 解析存储,保活 M4) */
|
||||
char *sp = strstr(buf, "service.");
|
||||
if (sp && tmp.nsvc < MEOW_MAX_SVCS) {
|
||||
@@ -833,6 +864,7 @@ void meow_parse_app_json(FILE *f, struct app *a)
|
||||
a->fonts = (char)(fonts < 0 ? 0 : (fonts > 2 ? 2 : fonts)); /* 注入 MEOW_FONT_TIER env */
|
||||
a->background = background ? '1' : 0; /* M4:后台服务注册权限 */
|
||||
a->background_audio = bg_audio ? '1' : 0; /* M4:后台播放保活 */
|
||||
a->background_keepalive = bg_keepalive ? '1' : 0; /* 批①:后台即保活(通用常驻) */
|
||||
strncpy(a->icon, icon, 128);
|
||||
a->nroute = tmp.nroute;
|
||||
if (tmp.nroute) memcpy(a->routes, tmp.routes, sizeof(a->routes[0]) * (size_t)tmp.nroute);
|
||||
@@ -1551,6 +1583,7 @@ static int launch_app_chain(struct app *a, const char *chain)
|
||||
unlink(NOTIF_ACTIVE);
|
||||
drain_input();
|
||||
meow_nav_begin(a->id, NULL); /* 转后台时导航栈已清;回前台从裸态重建 */
|
||||
ams_report_fg(a->id); /* 批①:单向 best-effort 上报 amsd 置 AMS_FG */
|
||||
}
|
||||
if (!resumed) {
|
||||
/* 二进制依赖启动前检查(app.json depends):required 缺失阻断启动,optional 缺失放行。
|
||||
@@ -1931,14 +1964,17 @@ static int launch_app_chain(struct app *a, const char *chain)
|
||||
break;
|
||||
}
|
||||
if (meow_nav_exit_pending()) {
|
||||
/* M4 后台播放保活:声明 background_audio 且该 App 媒体会话 PLAYING → 不终止,
|
||||
* 进程+音频流保留转后台(UI 冻结走 §10.5 SDK present 自抑,**非 SIGSTOP**——
|
||||
* SIGSTOP 会冻结同进程播放线程断供 PCM,§10.5 真机实证)。登记失败
|
||||
*(槽满/已存在)回落下方真退序列。卡拔例外不适用保活(bg 表 tick 照杀)。 */
|
||||
/* 批①后台保活:声明 background_keepalive → 恒保活;或声明 background_audio 且该 App
|
||||
* 媒体会话活跃(PLAYING/PAUSED/BUFFER,见 meow_media_app_resident)→ 保活。进程+音频流
|
||||
* 保留转后台(UI 冻结走 §10.5 SDK present 自抑,**非 SIGSTOP**——SIGSTOP 会冻结同进程
|
||||
* 播放线程断供 PCM,§10.5 真机实证)。登记失败(槽满/已存在)回落下方真退序列。
|
||||
* 卡拔例外不适用保活(bg 表 tick 照杀)。 */
|
||||
if (meow_bg_should_keep(a->background_audio == '1',
|
||||
meow_media_app_playing(a->id)) &&
|
||||
meow_bg_add(a->id, pid, out_fd, app_on_card) == 0) {
|
||||
logmsg("bg: app %s nav-exit -> 后台保活(播放中,pid=%d 保留,SDK present 自抑)",
|
||||
meow_media_app_resident(a->id),
|
||||
a->background_keepalive == '1') &&
|
||||
meow_bg_add(a->id, pid, out_fd, app_on_card,
|
||||
a->background_keepalive == '1') == 0) {
|
||||
logmsg("bg: app %s nav-exit -> 后台保活(活跃(播放/暂停/缓冲),pid=%d 保留,SDK present 自抑)",
|
||||
a->name, (int)pid);
|
||||
to_background = 1;
|
||||
break;
|
||||
@@ -2177,6 +2213,7 @@ static int launch_app_chain(struct app *a, const char *chain)
|
||||
meow_dirty_add(0, SB_BAR_Y, fb_xres, SB_BAR_H);
|
||||
settings_load();
|
||||
meow_nav_exit(); /* 前台会话导航栈清栈(App 本体栈内存活;回前台时裸态重建) */
|
||||
ams_report_bg(a ? a->id : "", pid); /* 批①:单向 best-effort 上报 amsd 置 AMS_BG */
|
||||
return 0;
|
||||
}
|
||||
/* §10.5:App 前台会话结束,清会话标记(ipc_dispatch 不再受理 MSG_NOTIF_OPEN) */
|
||||
|
||||
Reference in new issue
Block a user