Bug1: SDK meow_ui_media 按 g_last_state 本地判 play/pause,但 ncm 走自有 ipc_media 线程不经 SDK meta 上报 → g_last_state 恒 0 → 恒发 cmd=1(播放),播放中按键无效。 修:SDK 164 恒发 cmd=6 toggle(删 g_last_state 判定),ncm apply_playctl case 6 按 player_manager_state() 当前态翻转(源是状态权威);launcher meow_media/util 本就透传 cmd 不动结构,仅 meow_ipc.h/SPEC_REF 注释补 6=toggle。媒体卡片/NP 页 按钮(按 launcher 侧 s->state 判,来自 META 是准的)维持现状。 Bug2: App 前台时状态栏为 launcher 叠加层,App 内 SDK 改音量/亮度只写 settings.conf+DAC,launcher meow_settings 内存表不感知 → g_sys.vol 停旧值。 修:app_overlay_statusbar 前插 app_overlay_settings_poll——1s 节流 stat settings.conf,mtime 变才 meow_settings_init 重读+sync 缓存+g_sys.vol/brightness (meow_settings 新增 meow_settings_file_path() 访问器防硬编码分叉)。 验证:宿主 test_sdk_input_keys 19/19(K4 改 toggle 断言)、test_media +cmd=6 透传用例 ALL PASS、ncm bench/toggle_sim 10/10(新)、player_flow/cache_evict sim PASS、ncm core 宿主+qemu-mipsel PASS、test_settings_brightness PASS; mipsel 交叉 -Wall -Wextra 0 warning(改动文件单独验+整构建)。 真机(0.7.91):ncm 热更(.new+mv)后 autoplay(Docu) 起播缓存曲 → meow_ipc playctl 6 二连发 → paused(pos=139691)/resumed 日志实证 toggle 全链路。 md5:ncm 8f10eee5 / meow_ui.a 7b359ec9(gitignore)/ launcher eba4f2b2 (/usr/bin 只读,fw_content.conf 已更新待固件)。物理键 164 实体按压留用户终验。
97 lines
4.1 KiB
C
97 lines
4.1 KiB
C
/* bench/toggle_sim.c — MSG_PLAYCTL cmd=6(toggle) 离线回归(0 真实请求)。
|
||
*
|
||
* 背景(真机 bug):物理播放/暂停键(164)在 SDK 侧曾按「最近上报 state」本地判 play/pause,
|
||
* 但 ncm 走自有 ipc_media 线程、不经 SDK meow_ui_media_meta 上报 → SDK 侧 state 恒 0 →
|
||
* 恒发 cmd=1(播放),播放中按键无效。修法:SDK 恒发 cmd=6 toggle,源侧(本文件 apply_playctl)
|
||
* 按自身当前态翻转——源是状态权威。
|
||
*
|
||
* 同 TU 平移 app/play/ipc_media.c(含 static apply_playctl),player_manager_* 用记录桩
|
||
* (-ffunction-sections + --gc-sections 丢弃未触达的 send_meta/ipc_thread 及其依赖)。
|
||
*
|
||
* 用例:
|
||
* T1 播放中 toggle → pause(1);
|
||
* T2 暂停中 toggle → pause(0);
|
||
* T3 停止/缓冲中 toggle → pause(1)(player_manager_pause 内部按态过滤,no-op 安全);
|
||
* T4 旧 cmd 回归:1=play→pause(0) 2=pause→pause(1) 3=prev→next(-1) 4=next→next(1) 5=seek。
|
||
*
|
||
* 编译(宿主,ncm_app 目录下):
|
||
* gcc -Wall -Wextra -O2 -ffunction-sections -DJSMN_HEADER -I. -I../sdk -I../meow_launcherd \
|
||
* -Icore -Ivendor/jsmn -c bench/toggle_sim.c -o /tmp/tg.o
|
||
* gcc -O2 -Wl,--gc-sections -o toggle_sim /tmp/tg.o -lpthread -lm
|
||
* 运行:./toggle_sim (PASS/FAIL 退出码)
|
||
*/
|
||
#include "../app/ncm_app_internal.h"
|
||
|
||
/* ---- player_manager 记录桩(覆盖真实实现,仅记录调用)---- */
|
||
static int g_fake_state = NCM_PC_STOPPED;
|
||
static int g_pause_calls = 0, g_pause_last = -1;
|
||
static int g_next_calls = 0, g_next_last = 0;
|
||
static int g_seek_calls = 0; static int64_t g_seek_last = -1;
|
||
|
||
int player_manager_state(void) { return g_fake_state; }
|
||
void player_manager_pause(int on) { g_pause_calls++; g_pause_last = on; }
|
||
void player_manager_next(int dir) { g_next_calls++; g_next_last = dir; }
|
||
void player_manager_seek(int64_t ms) { g_seek_calls++; g_seek_last = ms; }
|
||
|
||
/* ---- 被平移 TU 引用但本测试不触达的符号(gc-sections 会丢,仅为防漏列桩)---- */
|
||
#include "../app/play/ipc_media.c"
|
||
|
||
static int failures = 0;
|
||
static void check(const char *name, int cond)
|
||
{
|
||
printf("%s %s\n", cond ? "PASS" : "FAIL", name);
|
||
if (!cond) failures++;
|
||
}
|
||
|
||
static m_playctl_t mk(uint32_t cmd, int64_t seek)
|
||
{
|
||
m_playctl_t c;
|
||
memset(&c, 0, sizeof c);
|
||
c.cmd = cmd;
|
||
c.seek_ms = seek;
|
||
return c;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
m_playctl_t c;
|
||
|
||
/* T1 播放中 toggle → 暂停 */
|
||
g_fake_state = NCM_PC_PLAYING;
|
||
c = mk(NCM_CTL_TOGGLE, 0);
|
||
apply_playctl(&c);
|
||
check("T1 PLAYING+toggle -> pause(1)", g_pause_calls == 1 && g_pause_last == 1);
|
||
|
||
/* T2 暂停中 toggle → 播放 */
|
||
g_fake_state = NCM_PC_PAUSED;
|
||
apply_playctl(&c);
|
||
check("T2 PAUSED+toggle -> pause(0)", g_pause_calls == 2 && g_pause_last == 0);
|
||
|
||
/* T3 停止/缓冲 toggle → pause(1)(内部按态过滤,不崩) */
|
||
g_fake_state = NCM_PC_STOPPED;
|
||
apply_playctl(&c);
|
||
check("T3 STOPPED+toggle -> pause(1) 内部过滤", g_pause_calls == 3 && g_pause_last == 1);
|
||
g_fake_state = NCM_PC_BUFFER;
|
||
apply_playctl(&c);
|
||
check("T3 BUFFER+toggle -> pause(1) 内部过滤", g_pause_calls == 4 && g_pause_last == 1);
|
||
|
||
/* T4 旧 cmd 回归 */
|
||
c = mk(NCM_CTL_PLAY, 0); apply_playctl(&c);
|
||
check("T4 PLAY -> pause(0)", g_pause_calls == 5 && g_pause_last == 0);
|
||
c = mk(NCM_CTL_PAUSE, 0); apply_playctl(&c);
|
||
check("T4 PAUSE -> pause(1)", g_pause_calls == 6 && g_pause_last == 1);
|
||
c = mk(NCM_CTL_PREV, 0); apply_playctl(&c);
|
||
check("T4 PREV -> next(-1)", g_next_calls == 1 && g_next_last == -1);
|
||
c = mk(NCM_CTL_NEXT, 0); apply_playctl(&c);
|
||
check("T4 NEXT -> next(1)", g_next_calls == 2 && g_next_last == 1);
|
||
c = mk(NCM_CTL_SEEK, 12345); apply_playctl(&c);
|
||
check("T4 SEEK -> seek(12345)", g_seek_calls == 1 && g_seek_last == 12345);
|
||
c = mk(99, 0); apply_playctl(&c); /* 未知 cmd:无动作不崩 */
|
||
check("T4 unknown cmd=99 -> no-op",
|
||
g_pause_calls == 6 && g_next_calls == 2 && g_seek_calls == 1);
|
||
|
||
printf("\n%s (%d failure%s)\n", failures ? "RESULT: FAIL" : "RESULT: PASS",
|
||
failures, failures == 1 ? "" : "s");
|
||
return failures ? 1 : 0;
|
||
}
|