fix(bt): 批①叠加/穿透根治 — /tmp/meow_notif_active从布尔标志改为内容=前台归属app_id(App用MEOW_LOG_APP比较:前台照常上屏收输入/后台常驻自抑+排空输入/空=全抑制),SDK present+input共用共享判定meow_ui_overlay_suppressed_active,launcher 7处转场改写;宿主test_overlay_suppress(T2c)/notif_gesture/overlay_gate/bg全过,0warning;meow_ui.a变M6.36需重编+重链四App
This commit is contained in:
1 parent
6bab304660
commit
7a276f609e
6 files changed
+168
-77
No files matched your search
@@ -974,16 +974,33 @@ static int statusbar_touched(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- §10.5 叠加让位自抑(present 层)----
|
||||
* /tmp/meow_notif_active 存在 = 通知中心叠加会话进行中(launcher 正在 fb 上渲染面板)。
|
||||
* App 进程(非系统 UI 渲染者)此时不上屏;200ms 节流缓存存在性(别每帧 stat)。
|
||||
/* ---- §10.5 叠加让位自抑(present / input 共用判定)----
|
||||
* /tmp/meow_notif_active = 前台屏幕归属标记,**内容=当前前台 app_id**(空=菜单/叠加层覆盖/
|
||||
* 无前台单元,即「抑制全部 App」)。App 进程(非系统 UI 渲染者)据此判「我是否前台」:
|
||||
* - 内容==本进程 app_id(env MEOW_LOG_APP)→ 前台 → 照常上屏 / 收输入;
|
||||
* - 内容为空 → 菜单前台或被叠加层覆盖 → 全抑制(含自身);
|
||||
* - 内容为其它 app_id → 后台常驻(批①多 App)/非前台 → 自抑上屏 + 排空输入。
|
||||
* 200ms 节流缓存存在性+内容(别每帧 open/stat)。
|
||||
* 计数 g_overlay_suppressed 供宿主单测断言(meow_gfx_overlay_suppressed_count)。 */
|
||||
static unsigned long long g_overlay_suppressed = 0;
|
||||
/* §后台化保活-残帧:记录「上一次 present 是否处于叠加自抑态」,用于在抑制→不抑制的恢复边沿
|
||||
* 强制整帧重画(盖掉 launcher 在后台化期间画进 buffer0 的桌面/主界面帧)。 */
|
||||
static int g_was_overlay_suppressed = 0;
|
||||
|
||||
static int overlay_present_suppressed(void)
|
||||
/* 本进程 app_id(env MEOW_LOG_APP,launcher 注入)= 判「我是否前台」的身份锚。 */
|
||||
static const char *overlay_own_app(void)
|
||||
{
|
||||
static const char *s = NULL;
|
||||
if (!s) {
|
||||
const char *e = getenv("MEOW_LOG_APP");
|
||||
s = (e && e[0]) ? e : "";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* §批①多 App 后台常驻:present 层与 input 层共用的「是否自抑」判定(单一实现,防两端漂移)。
|
||||
* 系统 UI(launcher 渲染面板/主界面)恒 0。返回 1=本进程应自抑上屏+排空输入。 */
|
||||
int meow_ui_overlay_suppressed_active(void)
|
||||
{
|
||||
if (meow_ui_sys_render_enabled()) return 0; /* launcher(系统 UI)渲染面板,照常上屏 */
|
||||
static char s_path[108];
|
||||
@@ -998,7 +1015,29 @@ static int overlay_present_suppressed(void)
|
||||
unsigned long long now = now_ms();
|
||||
if (s_last_chk && now - s_last_chk < MEOW_OVERLAY_CHK_MS) return s_last_res;
|
||||
s_last_chk = now;
|
||||
s_last_res = (access(s_path, F_OK) == 0) ? 1 : 0;
|
||||
{
|
||||
char owner[48];
|
||||
int have = 0;
|
||||
owner[0] = 0;
|
||||
int fd = open(s_path, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
ssize_t n = read(fd, owner, sizeof(owner) - 1);
|
||||
close(fd);
|
||||
if (n > 0) owner[n] = 0;
|
||||
have = 1; /* 文件存在(无论内容)→ 处于抑制管控 */
|
||||
} else {
|
||||
have = 0; /* 文件不存在 → 无抑制 */
|
||||
}
|
||||
if (!have) {
|
||||
s_last_res = 0;
|
||||
} else if (owner[0] == 0) {
|
||||
s_last_res = 1; /* 空内容=全抑制(菜单前台/叠加层覆盖) */
|
||||
} else {
|
||||
const char *me = overlay_own_app();
|
||||
/* 内容==本进程 app_id → 前台不抑制;否则(后台常驻/非前台)→ 抑制 */
|
||||
s_last_res = (strcmp(owner, me) == 0) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
return s_last_res;
|
||||
}
|
||||
|
||||
@@ -1010,9 +1049,10 @@ static void present(void)
|
||||
if (!(g_dirty_full || g_ndirty > 0)) return;
|
||||
/* §10.5 叠加让位自抑(仅 App 进程):App 前台播放中唤起通知中心时 launcher 不 SIGSTOP
|
||||
* (保 PCM 供流,ncm 播放线程同进程),改由 App 进程在此自抑上屏——绘制照常进 back_buf,
|
||||
* 只是不 present 到 fb,防 App 重绘穿透 launcher 叠加层。系统 UI 进程(launcher 渲染面板)
|
||||
* 不抑制。抑制期脏区保留累积(超上限自然升级整帧),标记消失后下一次 present 一次上屏。 */
|
||||
if (overlay_present_suppressed()) { g_overlay_suppressed++; g_was_overlay_suppressed = 1; return; }
|
||||
* 只是不 present 到 fb,防 App 重绘穿透 launcher 叠加层;后台常驻(批①)App 同判据自抑。
|
||||
* 系统 UI 进程(launcher 渲染面板)不抑制。抑制期脏区保留累积(超上限自然升级整帧),
|
||||
* 判定为「回到前台」后下一次 present 一次上屏。 */
|
||||
if (meow_ui_overlay_suppressed_active()) { g_overlay_suppressed++; g_was_overlay_suppressed = 1; return; }
|
||||
/* §后台化保活-残帧:抑制→不抑制的**恢复边沿**强制整帧重画。App 被 launcher 转后台保活
|
||||
* (/tmp/meow_notif_active 存在)期间 present 被自抑,back_buf 仍保留 App 自己的完整帧;
|
||||
* 但 launcher 已把桌面/主界面整帧画进 buffer0 盖在 App 残帧上。恢复前台时若只 present
|
||||
|
||||
@@ -140,28 +140,17 @@ static int meow_input_jack_debounce(void)
|
||||
return g_jack_changed_at && (now - g_jack_changed_at) < 800;
|
||||
}
|
||||
|
||||
/* ---- §10.5 叠加让位:通知中心叠加会话期输入排空(播放中 App 不被 SIGSTOP 的配套)----
|
||||
/* ---- §10.5 叠加让位:通知中心叠加会话期 / 批①后台常驻期 输入排空(播放中 App 不被 SIGSTOP 的配套)----
|
||||
* 媒体播放中的 App 前台唤起通知中心时 launcher 不冻结 App(保 PCM 供流,ncm 播放线程同进程),
|
||||
* App 输入线程仍在读同一批 evdev 设备(每 fd 各收一份事件副本,与 launcher 互不剥夺)——若不
|
||||
* 抑制,面板上的一次点击会被 App 再消费一次(如面板媒体卡片「暂停」与 App 同坐标控件双重触发)。
|
||||
* 故标记存在期:排空本进程 fd 队列并丢弃、EVIOCGKEY 位图静默对齐(不产生边沿语义,系统键动作
|
||||
* 叠加期由 launcher/watchdog 单侧承担)。200ms 节流缓存存在性(与 present 层同口径,别每圈 stat)。 */
|
||||
* 抑制,面板上的一次点击会被 App 再消费一次(如面板媒体卡片「暂停」与 App 同坐标控件双重触发);
|
||||
* 批①后台常驻 App 同理:前台 App(如 Hello)时,后台 ncm 的触摸必须被排空(一次交互只响应前台)。
|
||||
* 判据统一走 meow_ui_overlay_suppressed_active()(内容=前台 app_id;非前台/空=抑制)。抑制期:
|
||||
* 排空本进程 fd 队列并丢弃、EVIOCGKEY 位图静默对齐(不产生边沿语义,系统键动作叠加期由
|
||||
* launcher/watchdog 单侧承担)。200ms 节流缓存由共享判定承担(与 present 层同口径)。 */
|
||||
static int overlay_input_suppressed(void)
|
||||
{
|
||||
static char s_path[108];
|
||||
static int s_path_init = 0;
|
||||
static unsigned long long s_last_chk = 0;
|
||||
static int s_last_res = 0;
|
||||
if (!s_path_init) {
|
||||
const char *e = getenv("MEOW_NOTIF_ACTIVE_FILE"); /* 宿主/单测覆写(进程内只解析一次) */
|
||||
snprintf(s_path, sizeof s_path, "%s", (e && e[0]) ? e : "/tmp/meow_notif_active");
|
||||
s_path_init = 1;
|
||||
}
|
||||
unsigned long long now = now_ms();
|
||||
if (s_last_chk && now - s_last_chk < 200) return s_last_res;
|
||||
s_last_chk = now;
|
||||
s_last_res = (access(s_path, F_OK) == 0) ? 1 : 0;
|
||||
return s_last_res;
|
||||
return meow_ui_overlay_suppressed_active();
|
||||
}
|
||||
|
||||
/* ---- 系统按键语义(M2.55:SDK 输入层消化,App 前台也生效)----
|
||||
|
||||
@@ -163,6 +163,12 @@ int meow_gfx_is_device(void);
|
||||
* (仅 App 进程会自抑;宿主单测断言用,设备上无调用方)。 */
|
||||
unsigned long long meow_gfx_overlay_suppressed_count(void);
|
||||
|
||||
/* §批①多 App 后台常驻:本进程是否应自抑上屏+排空输入(present/input 层共用判定)。
|
||||
* /tmp/meow_notif_active 内容=前台 app_id:内容==本进程 app_id → 前台不抑制(返回 0);
|
||||
* 内容为空或其它 app_id → 菜单前台/叠加层覆盖/后台常驻 → 自动抑制(返回 1)。
|
||||
* 系统 UI(launcher)恒 0;200ms 节流缓存。meow_ui_gfx.c 实现,input 层复用。 */
|
||||
int meow_ui_overlay_suppressed_active(void);
|
||||
|
||||
/* 中文/日文字库(mfont)是否已加载(状态栏「蓝牙」CJK 与回退 "BT" 二选一)。 */
|
||||
int meow_gfx_mfont_ready(void);
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
/* test_overlay_suppress.c — §10.5 叠加让位 present 自抑宿主验证(离屏 480x720,16bpp)。
|
||||
*
|
||||
* 背景:媒体播放中的 App 前台唤起通知中心时 launcher 不 SIGSTOP(保 PCM 供流),改由 SDK
|
||||
* present 层见 /tmp/meow_notif_active(宿主用 MEOW_NOTIF_ACTIVE_FILE 覆写)自抑上屏。
|
||||
* present 层见 /tmp/meow_notif_active(宿主用 MEOW_NOTIF_ACTIVE_FILE 覆写)自抑上屏;
|
||||
* 批①后台常驻后标记**内容化**:内容=当前前台 app_id(空=菜单/叠加=全抑制)。本测试同时验证
|
||||
* 批①多 App 常驻的「前台/后台」判定:内容==本进程 app_id(env MEOW_LOG_APP)→ 前台不抑制;
|
||||
* 内容为其它 app_id / 空 → 后台常驻/被覆盖 → 自抑。
|
||||
*
|
||||
* 覆盖:
|
||||
* T1 无标记:flush 正常上屏(frames_presented 递增,抑制计数 0);
|
||||
* T2 有标记:flush 被抑制(只画进 back_buf 不 present:frames 不变、抑制计数递增);
|
||||
* T2b 抑制期第二次 flush 仍被抑制(200ms 节流缓存内行为一致);
|
||||
* T3 标记消失:下一次 flush 恢复上屏(抑制期累积脏区一次上屏,无需重画);
|
||||
* T4 系统 UI 进程(launcher,system_mode=1)即使有标记也不抑制(面板必须照常上屏)。
|
||||
* T1 无标记:flush 正常上屏(frames_presented 递增,抑制计数 0);
|
||||
* T2 标记=其它 app_id(后台常驻)→ 抑制(只画进 back_buf 不上屏:frames 不变、计数递增);
|
||||
* T2b 抑制期第二次 flush 仍被抑制(200ms 节流缓存内行为一致);
|
||||
* T2c 标记=自身 app_id(前台 App)→ 不抑制(恢复上屏,恢复边沿整帧重画;计数不再增长);
|
||||
* T3 标记=空内容(菜单/叠加全抑制)→ 仍抑制;
|
||||
* T3b 标记消失 → 恢复上屏(抑制期累积脏区一次上屏,无需重画);
|
||||
* T4 系统 UI 进程(launcher,system_mode=1)即使有标记也不抑制(面板必须照常上屏)。
|
||||
*
|
||||
* 编译(宿主 gcc,链真实 gfx/sys/theme/vol/log/widget/input/activity/dialog/ime + 打桩 font/global):
|
||||
* gcc -Wall -Wextra -o test_overlay_suppress test_overlay_suppress.c test_host_stub.c \
|
||||
@@ -26,13 +31,16 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define MARKER "/tmp/test_notif_active_sdk"
|
||||
#define MARKER "/tmp/test_notif_active_sdk"
|
||||
#define SELF_ID "testapp"
|
||||
|
||||
static void marker_write(void)
|
||||
static void marker_write(const char *content)
|
||||
{
|
||||
int fd = open(MARKER, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
assert(fd >= 0);
|
||||
if (write(fd, "1", 1) < 0) assert(0);
|
||||
if (content && content[0]) {
|
||||
if (write(fd, content, strlen(content)) < 0) assert(0);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -40,6 +48,7 @@ int main(void)
|
||||
{
|
||||
setenv("MEOW_UI_DUMP", "/tmp/overlay_suppress.ppm", 1);
|
||||
setenv("MEOW_NOTIF_ACTIVE_FILE", MARKER, 1);
|
||||
setenv("MEOW_LOG_APP", SELF_ID, 1); /* 本测试进程身份=前台/后台的判定锚 */
|
||||
unlink(MARKER);
|
||||
meow_ui_opts o = { 480, 720 };
|
||||
assert(meow_ui_init(&o) == 0);
|
||||
@@ -53,15 +62,15 @@ int main(void)
|
||||
assert(meow_gfx_overlay_suppressed_count() == 0);
|
||||
printf("T1 PASS: no marker -> presented=1 suppressed=0\n");
|
||||
|
||||
/* T2:有标记 → 抑制(等 >200ms 越过存在性节流缓存) */
|
||||
marker_write();
|
||||
/* T2:标记=其它 app_id(后台常驻 App)→ 抑制(等 >200ms 越过存在性节流缓存) */
|
||||
marker_write("ncm");
|
||||
usleep(250000);
|
||||
unsigned long long f0 = meow_ui_frames_presented();
|
||||
meow_ui_clear(0x223344);
|
||||
meow_ui_flush();
|
||||
assert(meow_ui_frames_presented() == f0);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 1);
|
||||
printf("T2 PASS: marker present -> suppressed (frames frozen at %llu)\n", f0);
|
||||
printf("T2 PASS: marker=other app -> suppressed (frames frozen at %llu)\n", f0);
|
||||
|
||||
/* T2b:抑制期再次 flush 仍抑制(节流缓存内一致) */
|
||||
meow_ui_clear(0x334455);
|
||||
@@ -70,24 +79,43 @@ int main(void)
|
||||
assert(meow_gfx_overlay_suppressed_count() == 2);
|
||||
printf("T2b PASS: still suppressed within throttle window\n");
|
||||
|
||||
/* T3:标记消失 → 恢复上屏(抑制期累积的整帧脏一次上屏,无需重画) */
|
||||
/* T2c:标记=自身 app_id(前台 App)→ 不抑制(批①前后台判定核心;恢复边沿整帧重画一次上屏) */
|
||||
marker_write(SELF_ID);
|
||||
usleep(250000);
|
||||
meow_ui_clear(0x445566);
|
||||
meow_ui_flush();
|
||||
assert(meow_ui_frames_presented() == f0 + 1);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 2); /* 不再增长(前台不抑制) */
|
||||
printf("T2c PASS: marker=self -> foreground, present resumed (accumulated dirty flushed)\n");
|
||||
|
||||
/* T3:标记=空内容(菜单/叠加层覆盖=全抑制)→ 仍抑制 */
|
||||
marker_write("");
|
||||
usleep(250000);
|
||||
unsigned long long f1 = meow_ui_frames_presented();
|
||||
meow_ui_clear(0x556677);
|
||||
meow_ui_flush();
|
||||
assert(meow_ui_frames_presented() == f1);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 3);
|
||||
printf("T3 PASS: empty marker (menu/overlay) -> suppressed\n");
|
||||
|
||||
/* T3b:标记消失 → 恢复上屏(抑制期累积的整帧脏一次上屏) */
|
||||
unlink(MARKER);
|
||||
usleep(250000);
|
||||
meow_ui_flush();
|
||||
assert(meow_ui_frames_presented() == f0 + 1);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 2);
|
||||
printf("T3 PASS: marker gone -> present resumed (accumulated dirty flushed)\n");
|
||||
assert(meow_ui_frames_presented() == f1 + 1);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 3);
|
||||
printf("T3b PASS: marker gone -> present resumed (accumulated dirty flushed)\n");
|
||||
|
||||
/* T4:系统 UI 进程(launcher)不抑制——通知中心面板本身必须照常上屏 */
|
||||
meow_ui_sys_set_system_mode(1);
|
||||
assert(meow_ui_sys_render_enabled() == 1);
|
||||
marker_write();
|
||||
marker_write("ncm");
|
||||
usleep(250000);
|
||||
unsigned long long f1 = meow_ui_frames_presented();
|
||||
meow_ui_clear(0x445566);
|
||||
unsigned long long f2 = meow_ui_frames_presented();
|
||||
meow_ui_clear(0x667788);
|
||||
meow_ui_flush();
|
||||
assert(meow_ui_frames_presented() == f1 + 1);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 2); /* 不再增长 */
|
||||
assert(meow_ui_frames_presented() == f2 + 1);
|
||||
assert(meow_gfx_overlay_suppressed_count() == 3); /* 不再增长 */
|
||||
unlink(MARKER);
|
||||
printf("T4 PASS: system-UI process (launcher) never suppressed\n");
|
||||
|
||||
|
||||
Reference in new issue
Block a user