/* test_np_keys.c — 宿主单测:Now Playing 播放页/歌词页物理键分发(Task C)。 * * 背景(真机现象):桌面播放页与歌词页上,音量键 + 播放键「完全无反应」。 * 根因(now_playing.c):run_now_playing() 原先只接播放键(164)与电源键,未接音量键 * (114/115),导致播放页/歌词页(同一循环,与页无关)调不了音量。 * * 本测复现 run_now_playing() 的按键动作应用(np_apply_key_actions):音量键走 * settings_volume_adj(±step)、播放键走 meow_media_playctl(按会话当前态 1=播放 2=暂停)。 * 断言: * K1 音量减边沿 → settings_volume_adj(-step); * K2 音量加边沿 → settings_volume_adj(+step); * K3 播放键边沿 + 会话正在播放 → meow_media_playctl(2,0)(暂停); * K4 播放键边沿 + 会话已暂停 → meow_media_playctl(1,0)(播放); * K5 播放键边沿 + 无会话 → 不下发(空态不误报); * K6 无任何边沿 → 两个回调都不触发; * K7 音量/播放边沿都会更新 last_input(自动息屏计时复位)。 * * 编译(在 patch_v2/meow_launcherd 下): * gcc -Wall -Wextra -I../sdk -I. -ffunction-sections -fdata-sections \ * -Wl,--gc-sections -DMEOW_NP_KEYS_TEST \ * test_np_keys.c -o test_np_keys * ./test_np_keys * 说明:now_playing.c 用 #include 同 TU 平移(惯例同 test_vol_ramp_jack);-ffunction-sections * + --gc-sections 只保留 np_apply_key_actions 及其依赖,其余(渲染/控件/绘制)被回收, * 故仅需桩 settings_volume_adj/settings_volume_step/meow_media_playctl/now_ms/logmsg。 */ #include "now_playing.c" /* 同 TU #include:拿到 static np_apply_key_actions */ #include #include static int g_fails = 0; #define CHECK(cond, name) do { \ if (cond) printf(" PASS %s\n", name); \ else { printf(" FAIL %s (%s:%d)\n", name, __FILE__, __LINE__); g_fails++; } } while (0) /* ---- 桩:np_apply_key_actions 依赖的 launcher 外部符号 ---- */ int settings_volume_step = 5; static int g_adj_count = 0, g_adj_delta = 0; void settings_volume_adj(int delta) { g_adj_count++; g_adj_delta = delta; } static int g_playctl_count = 0; static uint32_t g_playctl_cmd = 0; static int64_t g_playctl_seek = 0; int meow_media_playctl(uint32_t cmd, int64_t seek_ms) { g_playctl_count++; g_playctl_cmd = cmd; g_playctl_seek = seek_ms; return 0; } static unsigned long long g_now = 100000; unsigned long long now_ms(void) { return g_now; } void logmsg(const char *fmt, ...) { (void)fmt; } /* 会话(meow_media_session_t 来自 meow_media.h,含 state 字段) */ static meow_media_session_t g_s; static void reset_callbacks(void) { g_adj_count = 0; g_adj_delta = 0; g_playctl_count = 0; g_playctl_cmd = 0; g_playctl_seek = 0; } int main(void) { memset(&g_s, 0, sizeof g_s); unsigned long long last_input = 0; /* K1 音量减边沿 → settings_volume_adj(-step) */ reset_callbacks(); last_input = 0; g_now = 100000; np_apply_key_actions(1, 0, 0, &g_s, &last_input); CHECK(g_adj_count == 1 && g_adj_delta == -settings_volume_step, "K1 vol-down edge -> settings_volume_adj(-step)"); CHECK(last_input == g_now, "K7a vol-down updates last_input"); /* K2 音量加边沿 → settings_volume_adj(+step) */ reset_callbacks(); last_input = 0; g_now = 100050; np_apply_key_actions(0, 1, 0, &g_s, &last_input); CHECK(g_adj_count == 1 && g_adj_delta == +settings_volume_step, "K2 vol-up edge -> settings_volume_adj(+step)"); CHECK(last_input == g_now, "K7b vol-up updates last_input"); /* K3 播放键边沿 + 正在播放 → MSG_PLAYCTL(2,0) 暂停 */ g_s.state = MEOW_MEDIA_PLAYING; reset_callbacks(); np_apply_key_actions(0, 0, 1, &g_s, &last_input); CHECK(g_playctl_count == 1 && g_playctl_cmd == 2 && g_playctl_seek == 0, "K3 play edge (playing) -> playctl pause(2)"); /* K4 播放键边沿 + 已暂停 → MSG_PLAYCTL(1,0) 播放 */ g_s.state = MEOW_MEDIA_PAUSED; reset_callbacks(); np_apply_key_actions(0, 0, 1, &g_s, &last_input); CHECK(g_playctl_count == 1 && g_playctl_cmd == 1 && g_playctl_seek == 0, "K4 play edge (paused) -> playctl play(1)"); /* K5 播放键边沿 + 无会话 → 不下发(并仍复位 last_input) */ reset_callbacks(); last_input = 0; g_now = 100100; np_apply_key_actions(0, 0, 1, NULL, &last_input); CHECK(g_playctl_count == 0, "K5 play edge (no session) -> no playctl"); CHECK(last_input == g_now, "K7c play edge updates last_input (no session)"); /* K6 无任何边沿 → 两个回调都不触发 */ reset_callbacks(); last_input = 0; np_apply_key_actions(0, 0, 0, &g_s, &last_input); CHECK(g_adj_count == 0 && g_playctl_count == 0, "K6 no edge -> no callbacks"); /* K7 音量递减时播放键不同时触发(音量边沿优先,播放单独判) */ g_s.state = MEOW_MEDIA_PLAYING; reset_callbacks(); np_apply_key_actions(1, 0, 1, &g_s, &last_input); CHECK(g_adj_count == 1 && g_playctl_count == 1, "K8 vol-down + play_edge both fire (independent)"); printf("\nRESULT: %s (%d fails)\n", g_fails ? "FAIL" : "ALL PASS", g_fails); return g_fails ? 1 : 0; }