fix(§10.5): 通知中心叠加媒体保活——播放中 App 不 SIGSTOP(修播放中滑通知中心音乐停)
- launcher: run_app_notif_overlay 入口 meow_media_app_playing() 判定(当前源+PLAYING+app_id 匹配) → 不 SIGSTOP/不 SIGCONT,App 续跑保 PCM;非播放中维持 SIGSTOP 模板;关闭时 unlink 标记挪到 恢复帧上屏后(防未冻结 App 抢 present 一帧回闪)。 - SDK gfx: present() 见 /tmp/meow_notif_active(env MEOW_NOTIF_ACTIVE_FILE 覆写)自抑上屏, 仅 App 进程(系统 UI/launcher 不抑制),200ms 节流 stat,脏区累积解除后一次上屏; meow_gfx_overlay_suppressed_count 供单测断言。 - SDK input: 叠加期排空丢弃本进程 evdev 副本 + EVIOCGKEY 位图静默对齐(防面板点击被 App 双重消费/解除后边沿误判),进入沿复位触摸状态机。 - 宿主:新 test_overlay_suppress T1-T4 + test_media §8(8 用例)全 PASS;test_notif_*/ test_sdk_*/test_vol_ramp_jack 等回归全过;zig-mipsel -Wall -Wextra 全 TU 0 warning。 - meow_launcherd fbb82036(/usr/bin 只读待固件,fw_content.conf 已更)/ meow_ui.a d6242fc2 / hello a073535a / files 2b799d07(已热更到卡);ncm 未重链(ncm_app 他 agent 在改)。
This commit is contained in:
1 parent
820d1e52bf
commit
ad9778476a
19 files changed
+254
-13
No files matched your search
@@ -1201,6 +1201,9 @@ static void notify_app_crash(const char *pkg, int status)
|
||||
* ① SIGSTOP App → ② 写 /tmp/meow_notif_active(+ /tmp/meow_power_menu_active 让 watchdog 让位)
|
||||
* → ③ pm_capture_app_frame 读回 App 帧当背景 → ④ run_notif_center(apps={a},1) 叠加渲染
|
||||
* + 接管输入 → ⑤ 关闭后恢复 App 帧 → unlink active → SIGCONT App。
|
||||
* 媒体保活分支(定案):当前媒体源==本 App 且 PLAYING(meow_media_app_playing)→ ①不 SIGSTOP、
|
||||
* ⑤不 SIGCONT;App 继续跑保 PCM 供流,上屏由 SDK present 层见 ②的标记自抑,输入由 SDK
|
||||
* 输入线程见标记排空(防面板点击被 App 双重消费)。非播放中 App 维持 SIGSTOP 模板。
|
||||
* 差异:背景=App 帧(非应用列表);关闭后回 App(非回 run_menu);点通知首期 = dismiss + 关面板
|
||||
* + SIGCONT 回当前 App(不跨 app 启动,见 NOTIF_CENTER_APP_OVERLAY_PLAN §3.2)。
|
||||
* App 崩溃探测:run_notif_center 循环内 read /proc/<pid>/stat 状态位(zombie)周期探测
|
||||
@@ -1210,14 +1213,25 @@ static void notify_app_crash(const char *pkg, int status)
|
||||
static int run_app_notif_overlay(struct app *a, pid_t pid)
|
||||
{
|
||||
if (!back_buf_ok || !fb) { logmsg("notif-overlay: no back_buf (direct mode) skip"); return 0; }
|
||||
logmsg("notif-overlay: open (app=%s pid=%d) SIGSTOP", a->name, pid);
|
||||
if (kill(pid, SIGSTOP) < 0) {
|
||||
logmsg("notif-overlay: SIGSTOP %d fail: %s", pid, strerror(errno));
|
||||
/* 媒体保活(定案):当前媒体源==本前台 App 且 state==PLAYING → 不 SIGSTOP。ncm 等播放类
|
||||
* App 的播放线程同进程,冻结即 PCM 断供(真机报告:播放中滑下通知中心音乐停)。改为:
|
||||
* App 继续跑(音频照常喂 audiod、媒体上报照常),SDK present 层见 /tmp/meow_notif_active
|
||||
* 自抑上屏(只画进 back_buf 不 present,防重绘穿透叠加层);关闭时不补 SIGCONT(没 STOP 过)。
|
||||
* 非播放中 App 维持现状 SIGSTOP。 */
|
||||
int keep_running = meow_media_app_playing(a->id);
|
||||
if (keep_running) {
|
||||
logmsg("notif-overlay: open (app=%s pid=%d) PLAYING -> no SIGSTOP (SDK present suppressed)",
|
||||
a->name, pid);
|
||||
} else {
|
||||
/* 等 App 进入 stopped 态(/proc/pid/stat 状态位 'T';超时兜底);frozen 后才能读回帧 */
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (proc_is_stopped(pid)) break;
|
||||
usleep(10000);
|
||||
logmsg("notif-overlay: open (app=%s pid=%d) SIGSTOP", a->name, pid);
|
||||
if (kill(pid, SIGSTOP) < 0) {
|
||||
logmsg("notif-overlay: SIGSTOP %d fail: %s", pid, strerror(errno));
|
||||
} else {
|
||||
/* 等 App 进入 stopped 态(/proc/pid/stat 状态位 'T';超时兜底);frozen 后才能读回帧 */
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (proc_is_stopped(pid)) break;
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 让位标记:/tmp/meow_notif_active(§10.5 语义同 powmenu_active)。当前 watchdog 只认
|
||||
@@ -1240,19 +1254,27 @@ static int run_app_notif_overlay(struct app *a, pid_t pid)
|
||||
g_notif_ctrl_pid = 0;
|
||||
int died = g_notif_ctrl_died;
|
||||
|
||||
unlink(NOTIF_ACTIVE);
|
||||
unlink(POWMENU_ACTIVE);
|
||||
if (died) {
|
||||
/* App 已死:不 SIGCONT、不恢复死帧;back_buf 交还 run_menu 统一重绘 */
|
||||
unlink(NOTIF_ACTIVE);
|
||||
unlink(POWMENU_ACTIVE);
|
||||
logmsg("notif-overlay: app died during session -> unified exit path");
|
||||
return 1;
|
||||
}
|
||||
/* 恢复 App 帧(run_notif_center 关面板后 back_buf 已还原为背景=App 帧;再拍一次兜底
|
||||
* 覆盖非动画关闭路径)+ SIGCONT。 */
|
||||
* 覆盖非动画关闭路径)。媒体保活路径(keep_running):先恢复帧再 unlink 标记——
|
||||
* App 未被冻结仍在跑,标记多留一拍可让 SDK present 自抑覆盖到恢复帧上屏之后,
|
||||
* 避免「标记先消失 → App 抢在恢复帧前 present 新帧 → 又被旧帧盖回」的一帧回闪。 */
|
||||
pm_capture_app_frame();
|
||||
meow_ui_flush();
|
||||
kill(pid, SIGCONT);
|
||||
logmsg("notif-overlay: closed -> SIGCONT app");
|
||||
unlink(NOTIF_ACTIVE);
|
||||
unlink(POWMENU_ACTIVE);
|
||||
if (!keep_running) {
|
||||
kill(pid, SIGCONT);
|
||||
logmsg("notif-overlay: closed -> SIGCONT app");
|
||||
} else {
|
||||
logmsg("notif-overlay: closed -> app never stopped (media keep-alive), no SIGCONT");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -120,6 +120,13 @@ int meow_media_has_source(void)
|
||||
return (s && s->state != MEOW_MEDIA_STOPPED) ? 1 : 0;
|
||||
}
|
||||
|
||||
int meow_media_app_playing(const char *app_id)
|
||||
{
|
||||
const meow_media_session_t *s = meow_media_current();
|
||||
if (!s || !app_id || !app_id[0]) return 0;
|
||||
return (s->state == MEOW_MEDIA_PLAYING && strcmp(s->app_id, app_id) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int send_playctl(const meow_media_session_t *s, uint32_t cmd, int64_t seek_ms)
|
||||
{
|
||||
if (!s || !s->used || !g_ops || !g_ops->send) return -1;
|
||||
|
||||
@@ -72,6 +72,10 @@ const meow_media_session_t *meow_media_current(void);
|
||||
/* 是否有活动媒体源:当前源存在且 state != 0(停止)。通知中心卡片/播放页据此显示。 */
|
||||
int meow_media_has_source(void);
|
||||
|
||||
/* §10.5 叠加会话保活判定:当前源(最近活跃会话)存在、state==PLAYING 且 app_id 匹配。
|
||||
* launcher 据此决定通知中心叠加不 SIGSTOP 该 App(保 PCM 供流),SDK present 层自抑上屏。 */
|
||||
int meow_media_app_playing(const char *app_id);
|
||||
|
||||
/* 向当前源下发 PLAYCTL(卡片按钮/播放页/媒体键/控制器)。返回 0=已发,-1=无源/发送失败。 */
|
||||
int meow_media_playctl(uint32_t cmd, int64_t seek_ms);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* 4) PLAYCTL 下发字节格式(socketpair 对端可读回 MSG_PLAYCTL 帧,cmd/seek 正确);
|
||||
* 5) meow_media_playctl 无源 → -1;
|
||||
* 6) clear(app) 清会话 → current()=NULL。
|
||||
* 8) meow_media_app_playing(§10.5 叠加保活分支:当前源+PLAYING+app_id 匹配才 1)。
|
||||
* 只依赖 meow_media.c + meow_ipc.h(纯 C),宿主 gcc 直编。
|
||||
*/
|
||||
#include <stdio.h>
|
||||
@@ -170,6 +171,26 @@ int main(void)
|
||||
fill_meta(&m, "", MEOW_MEDIA_PLAYING, 0, 0, "x", "y");
|
||||
CHECK(meow_media_meta(&m, sv[0]) == -1, "meta empty app_id == -1");
|
||||
|
||||
/* 8) §10.5 叠加保活分支判定 meow_media_app_playing(launcher 不 SIGSTOP 的入口判据) */
|
||||
meow_media_clear(NULL);
|
||||
CHECK(meow_media_app_playing("com.ncm") == 0, "app_playing: no source == 0");
|
||||
fill_meta(&m, "com.ncm", MEOW_MEDIA_PLAYING, 1000, 240000, "Song A", "Artist A");
|
||||
meow_media_meta(&m, sv[0]);
|
||||
CHECK(meow_media_app_playing("com.ncm") == 1, "app_playing: current+PLAYING+match == 1");
|
||||
CHECK(meow_media_app_playing("com.other") == 0, "app_playing: app_id mismatch == 0");
|
||||
CHECK(meow_media_app_playing("") == 0, "app_playing: empty app_id == 0");
|
||||
CHECK(meow_media_app_playing(NULL) == 0, "app_playing: NULL app_id == 0");
|
||||
fill_meta(&m, "com.ncm", MEOW_MEDIA_PAUSED, 1000, 240000, "Song A", "Artist A");
|
||||
meow_media_meta(&m, sv[0]);
|
||||
CHECK(meow_media_app_playing("com.ncm") == 0, "app_playing: PAUSED == 0 (SIGSTOP as usual)");
|
||||
fill_meta(&m, "com.ncm", MEOW_MEDIA_PLAYING, 2000, 240000, "Song A", "Artist A");
|
||||
meow_media_meta(&m, sv[0]);
|
||||
/* 当前源被别的 App 抢走(后者 PAUSED 也抢走「最近活跃」)→ 本 App 播放中也不再保活 */
|
||||
fill_meta(&m, "com.player2", MEOW_MEDIA_PAUSED, 0, 180000, "Song B", "Artist B");
|
||||
meow_media_meta(&m, sv[0]);
|
||||
CHECK(meow_media_app_playing("com.ncm") == 0, "app_playing: not current source == 0");
|
||||
meow_media_clear(NULL);
|
||||
|
||||
printf("\n%s (%d fails)\n", g_fails ? "FAILED" : "ALL PASS", g_fails);
|
||||
return g_fails ? 1 : 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user