feat(bt): 批①宽限期补充 — 全App入后台表(bg_since_ms)+未声明App宽限30min(MEOW_BG_GRACE_MS)超时回收+声明常驻/媒体活跃不清+槽满LRU回收最旧未声明;test_bgplay全过/0warning;devdocs APP_BACKGROUND_KEEPALIVE_P1 §9;M6.34需先重编meow_ui.a(meow_img_pixels)

This commit is contained in:
AskaEth committed 2026-09-04 01:48:31 +08:00
1 parent effce6d0db
commit 45c633868f
4 files changed
+264 -62

No files matched your search

+23 -7
View File
@@ -29,6 +29,12 @@
/* 后台保活 App 上限(同时驻留后台的播放中 App) */
#define MEOW_BG_MAX 4
/* 批①+宽限:无声明/媒体不活跃 App 入后台的宽限期(默认 30 分钟)。
* 语义:转后台(bg_since_ms)后超 MEOW_BG_GRACE_MS 未再启动 → meow_bg_tick 走真退序列
* SIGTERM→SIGKILL 回收(摘表 + 通知 amsd)。**声明常驻(keepalive=1)或媒体活跃
* (meow_media_app_resident=1)不清**。本批为编译期常量(30*60*1000 = 1800000ms);
* 后续可进设置/按 App 可配(待拍板)。 */
#define MEOW_BG_GRACE_MS 1800000u
/* 无头后台服务运行时槽上限(与 meow_acct.svcs 的 MEOW_MAX_SVCS 对齐) */
#define MEOW_SVC_RT_MAX 8
@@ -45,9 +51,10 @@ typedef struct meow_bg_entry {
pid_t pid;
int out_fd;
int on_card; /* 二进制在 TF 卡上(卡拔需 SIGTERM 防 SIGBUS) */
uint64_t term_at_ms; /* 卡拔 SIGTERM 发出时刻(0=未发;SIGKILL 兜底计时) */
uint64_t bg_since_ms; /* 批①:转后台时刻(monotonic ms,批③管理页/闲置回收用) */
char keepalive; /* 批①:1=background_keepalive 类(无媒体会话也保活);0=background_audio 类 */
uint64_t term_at_ms; /* 卡拔/宽限超时/槽满回收 SIGTERM 发出时刻(0=未发;SIGKILL 兜底计时) */
uint64_t bg_since_ms; /* 批①:转后台时刻(monotonic ms;宽限超时回收/槽满 LRU 掐最久用) */
char keepalive; /* 批①+宽限:1=声明常驻(background_keepalive,无限期不清);0=宽限期类
* (未声明/background_audio,媒体不活跃时超 bg_grace_ms 回收) */
} meow_bg_entry_t;
/* 无头后台服务运行时槽(静态声明在 meow_acct.svcs,此处为运行态)。 */
@@ -73,6 +80,8 @@ typedef struct meow_svc_rt {
/* 依赖注入。全 NULL 可用(log 静默、now_ms 内部 CLOCK_MONOTONIC、card_present 恒 1、
* 通知清理/发帧跳过)。
* on_bg_dead:后台保活 App 进程退出(status=waitpid 原始状态;正常/异常由回调方判);
* media_resident:该 App 媒体会话是否「活跃可驻留」(launcher 注入 meow_media_app_resident)。
* 批①+宽限用:宽限超时回收 / 槽满 LRU 判「媒体活跃不清不回收」;NULL=恒 0(视为不活跃)。
* on_svc_dead:服务槽最终消亡(stopping 走完/不重启死亡;熔断不算消亡,槽保留待复位);
* notif_clear_app:熔断时清该 App 全部通知,返回清除条数(<0=失败);
* send_frame:熔断广播 MSG_SYS(launcher 侧须先查连接存活再发);
@@ -82,6 +91,7 @@ typedef struct meow_bgplay_ops {
uint64_t (*now_ms)(void);
int (*card_present)(void);
void (*on_bg_dead)(const char *app_id, pid_t pid, int status);
int (*media_resident)(const char *app_id);
void (*on_svc_dead)(const char *app_id, const char *svc);
int (*notif_clear_app)(const char *app_id);
size_t (*send_frame)(int fd, uint16_t type, uint32_t req_id,
@@ -101,8 +111,11 @@ void meow_bgplay_init(const meow_bgplay_ops *ops);
int meow_bg_should_keep(int bg_audio_declared, int media_resident, int keepalive_declared);
/* ---- 后台保活 App 表 ---- */
/* 转后台:登记 app_id/pid/out_fd,keepalive 标记常驻类型(1=background_keepalive 类)。
* 返回 0=成功;MEOW_ERR_EXISTS=已在后台;MEOW_ERR_NOMEM=满。 */
/* 转后台:登记 app_id/pid/out_fd,keepalive 标记常驻类型(1=background_keepalive 类=无限期;
* 0=宽限期类=未声明/background_audio,媒体不活跃时超 bg_grace_ms 回收)。批①+宽限:**全 App**
* nav-exit 都经此入表;槽满(MEOW_BG_MAX=4)时 LRU 回收最久未激活(bg_since_ms 最旧)的**未声明**
* 槽(不回收声明常驻/媒体活跃);全为声明常驻/媒体活跃 → MEOW_ERR_NOMEM(调用方回落真退,保安全)。
* 返回 0=成功;MEOW_ERR_EXISTS=已在后台;MEOW_ERR_NOMEM=满且无可回收。 */
int meow_bg_add(const char *app_id, pid_t pid, int out_fd, int on_card, int keepalive);
/* 回前台:按 app_id 摘除槽(进程归还前台会话)。成功返回 0 且 *out_fd(可 NULL)带回
* 管道读端;未在后台返回 -1。 */
@@ -116,8 +129,11 @@ const meow_bg_entry_t *meow_bg_at(int i);
/* 表变化计数(add/take/回收 递增);菜单 1s tick 比对刷新「·后台」标注用。 */
uint32_t meow_bgplay_change_seq(void);
/* 周期调(主循环 ~10ms 排空点):waitpid WNOHANG 回收死亡后台 App(→on_bg_dead 清槽);
* 卡拔例外:on_card 槽在卡不在时 SIGTERM,500ms 未死 SIGKILL。 */
/* 周期调(主循环 ~10ms 排空点):waitpid WNOHANG 回收死亡后台 App(→on_bg_dead 清槽)。
* 终止触发(SIGTERM,TERM_GRACE_MS 后 SIGKILL):
* - 卡拔例外:on_card 槽在卡不在时终止(防 SIGBUS);
* - 批①+宽限 超时回收:未声明(keepalive=0)且媒体不活跃(media_resident=0)的槽,转后台超
* MEOW_BG_GRACE_MS 未再启动 → 回收(走真退序列 + 摘表 + 通知 amsd)。声明常驻/媒体活跃不清。 */
void meow_bg_tick(void);
/* ---- 无头后台服务 ---- */