- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘) - OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复 - ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640 - 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫) - 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
131 lines
5.1 KiB
C
131 lines
5.1 KiB
C
/* bench/nav_exit_sim.c — 任务2:home 根页左滑「回桌面后台」宿主验证。
|
||
*
|
||
* 场景(0 真实请求/0 真实 launcher):fake launcher IPC socket(MEOW_IPC_SOCK)。调
|
||
* ipc_media_nav_exit(),断言:
|
||
* ① fake launcher 收到一条 MSG_NAV 帧,nav_type==MEOW_NAV_EXIT、app_id=="dev.player.ncm";
|
||
* ② 本函数**不**置 g_app_quit(进程保留,媒体会话继续上报 PLAYING,任务2 ③ 保活前提)。
|
||
* 这验证「从网易云主页面侧滑返回不再退出进程,而请求 launcher 退后台(有歌在播则 M4 保活)」。
|
||
*
|
||
* 编译(宿主,ncm_app 目录下):
|
||
* gcc -O1 -DJSMN_HEADER -I. -Icore -Iapp -I../sdk -I../meow_launcherd \
|
||
* -c bench/nav_exit_sim.c -o /tmp/ne.o
|
||
* gcc -O1 -DJSMN_HEADER -I. -Icore -Iapp -I../sdk -I../meow_launcherd \
|
||
* -c app/play/ipc_media.c -o /tmp/ne_ipc.o
|
||
* gcc -O1 -o nav_exit_sim /tmp/ne.o /tmp/ne_ipc.o -lpthread
|
||
* 运行:./nav_exit_sim (0 网络;PASS/FAIL 退出码)
|
||
*/
|
||
#include "../app/ncm_app_internal.h"
|
||
#include "meow_ipc.h"
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <unistd.h>
|
||
#include <pthread.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/un.h>
|
||
|
||
ncm_app_state_t g_st;
|
||
ncm_play_run_t g_play = { .mu = PTHREAD_MUTEX_INITIALIZER, .state = NCM_PC_STOPPED, .cur_song = -1 };
|
||
volatile int g_app_quit = 0;
|
||
volatile int g_net_ready = 1;
|
||
int g_host_mock = 0;
|
||
|
||
size_t ncm_strlcpy(char *dst, const char *src, size_t sz)
|
||
{
|
||
size_t n = 0;
|
||
if (sz) { while (src[n] && n < sz - 1) { dst[n] = src[n]; n++; } dst[n] = 0; }
|
||
while (src[n]) n++;
|
||
return n;
|
||
}
|
||
void meow_log(meow_log_level lvl, const char *fmt, ...) { (void)lvl; (void)fmt; }
|
||
|
||
/* ipc_media.c 的其余依赖(本 sim 不驱动播放/封面/歌词,仅服务链接与消息类型) */
|
||
uint64_t meow_ui_time_ms(void) { return 0; }
|
||
int player_manager_playing_song(void) { return g_play.cur_song; }
|
||
int player_manager_current_song(ncm_song_t *out) { (void)out; return -1; }
|
||
void player_manager_pause(int on) { (void)on; }
|
||
void player_manager_next(int dir) { (void)dir; }
|
||
void player_manager_seek(int64_t ms) { (void)ms; }
|
||
int player_manager_state(void) { return g_play.state; }
|
||
const char *cover_current_path(void) { return NULL; }
|
||
int lyric_count(void) { return 0; }
|
||
|
||
/* ---- fake launcher ---- */
|
||
static const char *g_sock = "/tmp/nav_exit_launcher.sock";
|
||
static uint16_t g_got_type = 0;
|
||
static int g_got_nav_type = -1;
|
||
static char g_got_app[MEOW_APP_ID_MAX];
|
||
static int g_got = 0;
|
||
|
||
static void *server(void *arg)
|
||
{
|
||
(void)arg;
|
||
unlink(g_sock);
|
||
int lfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
if (lfd < 0) return NULL;
|
||
struct sockaddr_un a;
|
||
memset(&a, 0, sizeof a);
|
||
a.sun_family = AF_UNIX;
|
||
strncpy(a.sun_path, g_sock, sizeof a.sun_path - 1);
|
||
if (bind(lfd, (struct sockaddr *)&a, sizeof a) != 0) { close(lfd); return NULL; }
|
||
listen(lfd, 1);
|
||
int fd = accept(lfd, NULL, NULL);
|
||
if (fd < 0) { close(lfd); return NULL; }
|
||
uint8_t rbuf[MEOW_IPC_MAX];
|
||
ssize_t n = read(fd, rbuf, sizeof rbuf);
|
||
if (n >= (ssize_t)MEOW_IPC_HDR_LEN) {
|
||
uint32_t magic, len;
|
||
uint16_t ver, type;
|
||
memcpy(&magic, rbuf, 4); memcpy(&ver, rbuf + 4, 2); memcpy(&type, rbuf + 6, 2);
|
||
memcpy(&len, rbuf + 12, 4);
|
||
if (magic == MEOW_IPC_MAGIC && ver == MEOW_IPC_VERSION && len <= (uint32_t)(n - MEOW_IPC_HDR_LEN)) {
|
||
g_got_type = type;
|
||
if (type == MSG_NAV && len >= sizeof(m_nav_t)) {
|
||
m_nav_t nv;
|
||
memcpy(&nv, rbuf + MEOW_IPC_HDR_LEN, sizeof nv);
|
||
g_got_nav_type = (int)nv.nav_type;
|
||
nv.app_id[MEOW_APP_ID_MAX - 1] = 0;
|
||
snprintf(g_got_app, sizeof g_got_app, "%s", nv.app_id);
|
||
}
|
||
g_got = 1;
|
||
}
|
||
}
|
||
close(fd); close(lfd);
|
||
return NULL;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
int fail = 0;
|
||
setenv("MEOW_IPC_SOCK", g_sock, 1);
|
||
|
||
pthread_t th;
|
||
if (pthread_create(&th, NULL, server, NULL) != 0) { printf("FAIL server thread\n"); return 1; }
|
||
usleep(50000);
|
||
|
||
int rc = ipc_media_nav_exit();
|
||
pthread_join(th, NULL);
|
||
|
||
if (rc != 0) { printf("FAIL ipc_media_nav_exit rc=%d\n", rc); fail = 1; }
|
||
if (!g_got) { printf("FAIL fake launcher received no frame\n"); fail = 1; }
|
||
else if (g_got_type != MSG_NAV) {
|
||
printf("FAIL expected MSG_NAV (0x%04x) got 0x%04x\n", MSG_NAV, g_got_type);
|
||
fail = 1;
|
||
} else if (g_got_nav_type != MEOW_NAV_EXIT) {
|
||
printf("FAIL expected MEOW_NAV_EXIT got %d\n", g_got_nav_type);
|
||
fail = 1;
|
||
} else if (strcmp(g_got_app, "dev.player.ncm") != 0) {
|
||
printf("FAIL expected app_id dev.player.ncm got \"%s\"\n", g_got_app);
|
||
fail = 1;
|
||
} else {
|
||
printf("PASS nav_exit: type=0x%04x nav_type=EXIT app=%s\n", g_got_type, g_got_app);
|
||
}
|
||
if (g_app_quit != 0) { printf("FAIL g_app_quit set (process must stay alive for bg keepalive)\n"); fail = 1; }
|
||
else printf("PASS nav_exit did NOT set g_app_quit (process/alive, media keeps reporting PLAYING)\n");
|
||
|
||
unlink(g_sock);
|
||
if (fail) { printf("nav_exit_sim FAIL\n"); return 1; }
|
||
printf("nav_exit_sim PASS\n");
|
||
return 0;
|
||
}
|