/* test_lock_render.c — 锁屏首帧「全屏不透明底」宿主断言(§310 问题2-①/②)。 * * 背景(M6.4 真机):超时息屏→亮屏进锁屏时,App 刷新控件盖到锁屏上、未刷新区显示锁屏自带脏区。 * 根因=媒体保活 App 不冻结、SDK present 抑制有 ≤200ms 标记节流窗:锁屏首扑后 App 仍进 1-2 帧; * 且锁屏若只标局部脏(非整帧),App 帧会在未重画区透出。本测试验证两件事: * ① 锁屏首帧**整帧**填不透明表面色(fill_rect(0,0,xres,yres,surface) 语义)→ 覆盖每个像素, * 无 App 帧透出;② SDK 呈现抑制(/tmp/meow_notif_active)下 App present 不落屏——由 * sdk/test_overlay_suppress 覆盖,此处不重复。 * * 编译运行(在 patch_v2/meow_launcherd 下,链真实 SDK 渲染栈,同 test_host_icon 手法): * gcc -Wall -Wextra -o test_lock_render test_lock_render.c ../sdk/test_host_stub.c \ * ../sdk/meow_ui_gfx.c ../sdk/meow_ui_sys.c ../sdk/meow_ui_theme.c ../sdk/meow_ui_vol.c \ * ../sdk/meow_ui_log.c ../sdk/meow_ui_widget.c ../sdk/meow_ui_input.c ../sdk/meow_ui_activity.c \ * ../sdk/meow_ui_dialog.c ../sdk/meow_ui_ime.c ../sdk/meow_ui_str.c ../sdk/meow_ui_draw.c \ * ../sdk/meow_ui_view.c ../sdk/meow_notify_ipc.c ../sdk/meow_ui_anim.c ../sdk/meow_ui_box.c \ * ../sdk/meow_ui_media.c ../sdk/meow_pinyin.c -I../sdk -I. -DMEOW_UI_HOST_TEST -pthread * ./test_lock_render * 全 PASS -> exit 0。 */ #include #include #include "meow_ui.h" #include "meow_ui_internal.h" /* meow_ui_back_buf/pitch/bpp */ static int g_fail = 0; #define CHECK(cond, msg) do { \ if (cond) { printf("PASS %s\n", msg); } \ else { g_fail++; printf("FAIL %s\n", msg); } \ } while (0) int main(void) { meow_ui_opts o = { 480, 720 }; CHECK(meow_ui_init(&o) == 0, "sdk init 480x720"); unsigned char *buf = meow_ui_back_buf(); int pitch = meow_ui_back_buf_pitch(); int bpp = meow_ui_back_buf_bpp(); CHECK(buf != NULL && pitch > 0 && bpp >= 16, "back_buf present (pitch>0, bpp>=16)"); int w = pitch / (bpp / 8); int h = 720; CHECK(w == 480 && h == 720, "framebuffer geometry 480x720"); /* 「首帧全屏不透明底」:模拟 lk_draw 的 fill_rect(0,0,w,h,surface) —— 把整帧填一不透明色。 */ unsigned short fill = 0x1111; /* 不透明 RGB565(RGB565 无 alpha) */ for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) *(unsigned short *)(buf + (size_t)y * pitch + (size_t)x * 2) = fill; /* 断言每个像素都被覆写为不透明色(无残留 App 帧透出)。整帧覆盖 = 首帧全不透明。 */ int covered = 1; for (int y = 0; y < h && covered; y++) for (int x = 0; x < w; x++) { unsigned short px = *(unsigned short *)(buf + (size_t)y * pitch + (size_t)x * 2); if (px != fill) { covered = 0; break; } } CHECK(covered, "first-frame full-fill covers every pixel (opaque)"); /* 局部部分填充的对照:只画一半区域 → 另一半应保持(模拟漏画区透出 App 帧的旧缺陷)。 */ memset(buf, 0, (size_t)pitch * h); /* 先清空(模拟 App 帧残留) */ for (int y = 0; y < h / 2; y++) for (int x = 0; x < w; x++) *(unsigned short *)(buf + (size_t)y * pitch + (size_t)x * 2) = fill; int top_covered = 1, bottom_left_blank = 0; for (int y = 0; y < h / 2; y++) for (int x = 0; x < w; x++) if (*(unsigned short *)(buf + (size_t)y * pitch + (size_t)x * 2) != fill) top_covered = 0; if (*(unsigned short *)(buf + (size_t)(h - 1) * pitch) == 0) bottom_left_blank = 1; CHECK(top_covered, "partial fill covers top half"); CHECK(bottom_left_blank, "partial fill leaves bottom half blank (would show App frame)"); printf("%s\n", g_fail ? "SOME TESTS FAILED" : "ALL PASS"); return g_fail ? 1 : 0; }