feat: M6.10–M6.19 批量收编 + M6.19 推卡验收

- 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 推卡自刷验收全绿
This commit is contained in:
AskaEth committed 2026-09-03 12:16:01 +08:00
1 parent c2ee7626a4
commit 3d70a3dd2c
176 files changed
+15507 -597

No files matched your search

+201
View File
@@ -0,0 +1,201 @@
/* play/mem_watch.c — 边播边监控**取证**实现(接口见 mem_watch.h;agent 32bit 大文件 OOM 取证)。
*
* 归属演进(2026-09-02 定案,ARCHITECTURE_PRINCIPLES ③混合):**降载决策上收通用层**——
* A(DONTNEED 治理)+ C(/proc/meminfo Cached 监控)分别归 SDK meow_cachegov / meow_svc_perf;
* 本模块退化为「RssAnon 取证」:低频读 /proc/self/status(优先 RssAnon,缺失回退 VmRSS),
* 记录匿名内存峰值,**仅供日志**。不再驱动下载/预取降载(那由 meow_cachegov_download_paused
* / prefetch_paused 查询)。**绝不打断解码/播放**。
*
* 阈值滞后(仅用于取证 level 标注):
* kb >= CRITICAL → level=2;kb >= HIGH 且当前<2 → level=1;kb <= LOW → level=0;其它保持。
* 本模块自含:只依赖 pthread + meow_log(SDK 日志),不依赖 core/app 其它 TU。
*/
#include "mem_watch.h"
#include "../sdk/include/meow_ui_log.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* 默认阈值(设备缺省;宿主单测用 env/force 桩覆盖) */
#define MEM_WATCH_PERIOD_MS 500
#define MEM_WATCH_HIGH_KB (30 * 1024)
#define MEM_WATCH_LOW_KB (20 * 1024)
#define MEM_WATCH_CRITICAL_KB (40 * 1024)
struct mw_cfg {
int period_ms;
long high_kb;
long low_kb;
long critical_kb;
};
static struct mw_cfg g_cfg = {
.period_ms = MEM_WATCH_PERIOD_MS,
.high_kb = MEM_WATCH_HIGH_KB,
.low_kb = MEM_WATCH_LOW_KB,
.critical_kb = MEM_WATCH_CRITICAL_KB,
};
static pthread_mutex_t g_mu = PTHREAD_MUTEX_INITIALIZER;
static pthread_t g_thr;
static int g_thr_on;
static volatile int g_quit;
static long g_rss_anon_kb; /* 最近一次采样(KB;-1=不可读) */
static long g_peak_song_kb; /* 本曲匿名峰值(song_begin 清零) */
static int g_level; /* NCM_MEM_LVL_*(仅取证日志) */
static long g_forced_kb = -1; /* 宿主桩 ≥0 时替代真读 */
/* env 覆盖阈值:非法值回落默认。 */
static int env_int(const char *k, int def)
{
const char *e = getenv(k);
if (!e || !e[0]) return def;
int v = atoi(e);
return v > 0 ? v : def;
}
static long env_long(const char *k, long def)
{
const char *e = getenv(k);
if (!e || !e[0]) return def;
long v = atol(e);
return v > 0 ? v : def;
}
/* 读匿名 RSS(KB)。优先 RssAnon;缺则回退 VmRSS;都无 → -1。 */
static long read_rss_kb(void)
{
pthread_mutex_lock(&g_mu);
long forced = g_forced_kb;
pthread_mutex_unlock(&g_mu);
if (forced >= 0) return forced;
FILE *fp = fopen("/proc/self/status", "r");
if (!fp) return -1;
char line[256];
long anon = -1, rss = -1;
while (fgets(line, sizeof line, fp))
if (!strncmp(line, "RssAnon:", 8)) anon = atol(line + 8);
else if (rss < 0 && !strncmp(line, "VmRSS:", 6)) rss = atol(line + 6);
fclose(fp);
return anon >= 0 ? anon : rss;
}
static const char *level_str(int lvl)
{
switch (lvl) {
case NCM_MEM_LVL_HIGH: return "high";
case NCM_MEM_LVL_CRITICAL: return "critical";
default: return "normal";
}
}
static void *watch_thread(void *arg)
{
(void)arg;
while (!g_quit) {
long kb = read_rss_kb();
int lvl;
pthread_mutex_lock(&g_mu);
g_rss_anon_kb = kb;
if (kb > g_peak_song_kb) g_peak_song_kb = kb;
long hi = g_cfg.high_kb, lo = g_cfg.low_kb, cr = g_cfg.critical_kb;
/* 滞后三档(仅取证 level 标注) */
if (kb >= cr) lvl = NCM_MEM_LVL_CRITICAL;
else if (kb >= hi) lvl = (g_level == NCM_MEM_LVL_CRITICAL) ? NCM_MEM_LVL_CRITICAL : NCM_MEM_LVL_HIGH;
else if (kb <= lo) lvl = NCM_MEM_LVL_NORMAL;
else lvl = g_level; /* 滞后带:保持 */
if (lvl != g_level) {
meow_log(MEOW_LOG_INFO,
"[mem] rss_anon=%ldKB peak=%ldKB level=%s (H=%ldK/L=%ldK/C=%ldK)",
kb, g_peak_song_kb, level_str(lvl), hi, lo, cr);
}
g_level = lvl;
pthread_mutex_unlock(&g_mu);
usleep((useconds_t)g_cfg.period_ms * 1000u);
}
return NULL;
}
int mem_watch_start(void)
{
pthread_mutex_lock(&g_mu);
if (g_thr_on) { pthread_mutex_unlock(&g_mu); return 0; }
/* 开关(默认开;NCM_MEM_WATCH_ENABLED=0/off 关闭监控,行为退化为旧版零侵入) */
const char *en = getenv("NCM_MEM_WATCH_ENABLED");
if (en && (!en[0] || !strcmp(en, "0") || !strcmp(en, "off") || !strcmp(en, "false"))) {
pthread_mutex_unlock(&g_mu);
meow_log(MEOW_LOG_INFO, "[mem] watch disabled (NCM_MEM_WATCH_ENABLED=%s)", en);
return 0;
}
/* 阈值 env 覆盖(宿主单测) */
g_cfg.period_ms = env_int("NCM_MEM_WATCH_PERIOD_MS", MEM_WATCH_PERIOD_MS);
g_cfg.high_kb = env_long("NCM_MEM_WATCH_HIGH_KB", MEM_WATCH_HIGH_KB);
g_cfg.low_kb = env_long("NCM_MEM_WATCH_LOW_KB", MEM_WATCH_LOW_KB);
g_cfg.critical_kb = env_long("NCM_MEM_WATCH_CRITICAL_KB", MEM_WATCH_CRITICAL_KB);
g_quit = 0;
pthread_attr_t a;
pthread_attr_init(&a);
pthread_attr_setstacksize(&a, (size_t)(128 * 1024)); /* 同 ncm_thread_create 128KB(内存瘦身,OOM 修复) */
int rc = pthread_create(&g_thr, &a, watch_thread, NULL);
pthread_attr_destroy(&a);
if (rc != 0) { pthread_mutex_unlock(&g_mu); return -1; }
g_thr_on = 1;
pthread_mutex_unlock(&g_mu);
meow_log(MEOW_LOG_INFO,
"[mem] watch started period=%dms H=%ldK L=%ldK C=%ldK (RssAnon 优先)",
g_cfg.period_ms, g_cfg.high_kb, g_cfg.low_kb, g_cfg.critical_kb);
return 0;
}
void mem_watch_stop(void)
{
g_quit = 1;
pthread_mutex_lock(&g_mu);
if (g_thr_on) { g_thr_on = 0; pthread_detach(g_thr); }
pthread_mutex_unlock(&g_mu);
}
int mem_watch_level(void)
{
pthread_mutex_lock(&g_mu);
int v = g_level;
pthread_mutex_unlock(&g_mu);
return v;
}
long mem_watch_rss_anon_kb(void)
{
pthread_mutex_lock(&g_mu);
long v = g_rss_anon_kb;
pthread_mutex_unlock(&g_mu);
return v;
}
void mem_watch_song_begin(void)
{
long kb = read_rss_kb(); /* 起播即采样当前内存,本曲峰值从当前起算 */
pthread_mutex_lock(&g_mu);
g_peak_song_kb = kb;
pthread_mutex_unlock(&g_mu);
meow_log(MEOW_LOG_INFO, "[mem] song begin rss_anon=%ldKB", kb);
}
/* 播完/切歌释放钩子之后调用:落本曲峰值 + 重置计数。 */
void mem_watch_song_end(void)
{
pthread_mutex_lock(&g_mu);
long peak = g_peak_song_kb;
g_peak_song_kb = g_rss_anon_kb;
pthread_mutex_unlock(&g_mu);
meow_log(MEOW_LOG_INFO, "[mem] song end peak_anon=%ldKB (released)", peak);
}
void mem_watch_set_forced_kb(long kb)
{
pthread_mutex_lock(&g_mu);
g_forced_kb = kb;
pthread_mutex_unlock(&g_mu);
}