feat: M6.44+M6.45 收编 — 真机 0.8.45 现场保全(reader章节/key_router按键路由/WiFi连接修复/ncm bench+IME修复)
脏工作区现场收编:devdocs/local/m6_44_45_dirty_tracked.patch(46 个已跟踪文本文件,
+3090/-585, 已对 M6.43 基线干净适配) + m6_44_45_untracked_src.tar.gz 中 patch_v2/ 下
13 个新增源文件, 合成单个提交, 内容与容器工作树(R3ProII/patch_v2)逐字节一致。
- reader 章节: 新增 core/rdchapter.{h,c} — TXT 章节规范解析器, 扫描 512KB 码位对齐段文件
逐段流式识别标题行(行首缩进≤4/显示宽≤40/行内标点≤1 三重约束防误判), 输出标题+全书字符
偏移+段号/段内偏移+阿拉伯章号(中文数字归一), 首章前内容归"卷首"; book/reader/rdenc/
rdlayout/settings 接入章节跳转与进度锚点, 附 chapter_smoke/turn_repro/build_turn_repro.sh
- key_router 按键路由: 新增 meow_launcherd/key_router.{h,c} — launcher-UI 页物理键统一路由
(P1 仅音量键), 把读取边沿+防抖+长按 held+ramp 推进从 5 个会话收敛为进程内单开;
各页每圈 key_router_pump() 取防抖后边沿, 动作(调音量/光标导航)仍由调用页决定,
保留 run_menu 的 meow_mode 分支; App 前台 volume_page 武装时边沿抑制;
main_menu/now_playing/notif_center/settings_page/subpage 接入, 附 test_key_router_vol/test_np_keys
- WiFi 连接修复: meow_netmgrd connect 有界等待 wpa_state=COMPLETED(普通 10s/隐藏网络 15s,
env 可调)修设置页连接无响应; list_networks/scan_results 的 \xNN 转义还原始字节, 修中文 SSID
永不命中致新建同名 open 记录顶影; launcher netmgr_ipc 配读超时; 附 test_wifi_connect(桩
wpa_cli 驱动 static wifi_connect_ex), test_netmgrd.sh 补用例; wifi_page 同步
- ncm bench: 新增 bench/lyric_sim.c、bench/plpage_sim.c, vol_sync_sim 与 ncm core/app 同步
- SDK IME 修复: shift 大小写、K_ENTER 只提交不关、阻塞 IME 循环喂 on_tick 不被遮挡、
IME 打开 ~200ms TAP 冷却窗吞 stray-TAP; 附 sdk/test_ime_fix.c
- 同期: meow_audiod 音量异步 ACK 线程(代际防 fd/槽复用竞态)、watchdog 音量收编(首选 audiod
权威, settings.conf 覆盖路径)、panel 文件搜索(F1-④)与蓝牙只读详情(F1-③)、各类 build 脚本同步
范围红线: third_party/legado-E-main 原开发者未跟踪, 本次不入库(保留 devdocs/local tar 参考);
二进制不入库(后续重编); devdocs/ 不入库。59 文件全部在 patch_v2/ 下, 无 third_party/devdocs。
验证: git apply --check 干净; 59 文件 md5 与容器 patch_v2 逐一比对 59/59 一致(含
key_router.c/rdchapter.c/meow_ui_ime.c/test_wifi_connect.c 抽查); 可执行位保守
(check_lgpl_release.sh 100755, build_turn_repro.sh 100644 与容器一致)。
This commit is contained in:
1 parent
e87ccdf061
commit
7c7d891570
59 files changed
+5305
-590
No files matched your search
@@ -8,16 +8,17 @@ set -e
|
||||
cd "$(dirname "$0")"
|
||||
ROOT=../..
|
||||
CC="$ROOT/.tools/zig-mipsel-cc"
|
||||
INC="$ROOT/patch_v2/meow_launcherd" # meow_ipc.h(音量收编 v2:MSG_AUDIO_VOLUME/MSG_ACK)
|
||||
|
||||
if [ "$1" = "host" ]; then
|
||||
gcc -Wall -Wextra -Os -DWd_NO_MAIN -Wno-unused-function -Wno-unused-parameter \
|
||||
test_wd_fw.c -o test_wd_fw -lm
|
||||
gcc -Wall -Wextra -Os -I"$INC" -DWd_NO_MAIN -Wno-unused-function -Wno-unused-parameter \
|
||||
-Wno-unused-variable test_wd_fw.c -o test_wd_fw -lm
|
||||
./test_wd_fw
|
||||
exit $?
|
||||
fi
|
||||
|
||||
echo "== meow_watchdog (mipsel static) =="
|
||||
"$CC" -Os -Wall -Wextra -static meow_watchdog.c -o meow_watchdog
|
||||
"$CC" -Os -Wall -Wextra -static -I"$INC" meow_watchdog.c -o meow_watchdog
|
||||
ls -la meow_watchdog
|
||||
md5sum meow_watchdog
|
||||
file meow_watchdog
|
||||
@@ -19,7 +19,10 @@
|
||||
* (launcher 在 waitpid 轮询中消费;菜单期该进程靠 /tmp/meow_power_menu_active
|
||||
* 让位,绝不与 launcher 抢屏/抢键);launcher 画菜单,本进程不自绘。
|
||||
* 电源长按 ≥8s -> 强制关机兜底(仅当菜单未生效/launcher 未接管)。
|
||||
* 音量±(115/114) -> 写真实 DAC(CS43198 amixer numid=1/2)+ 持久化 settings.conf(同 launcher 同源)。
|
||||
* 音量±(115/114) -> 音量收编 v2(FUTURE_AUDIO 事项三):首选发 audiod 权威
|
||||
* MSG_AUDIO_VOLUME(audiod 写 DAC numid=1/2 + DSD_VOLUME + 持久化
|
||||
* settings.conf,同源同键单写者);audiod 未起(HibyOS/开机早期)
|
||||
* 才回退本地 amixer 直写兜底 + 本地持久化。
|
||||
* 插孔消抖:/sys/class/switch/{headset,balance} 变化后 800ms 内忽略音量键边沿
|
||||
* (插拔电气瞬态会在 ADC 键上产生幽灵按下,真机实证 2026-09-01)。
|
||||
* 播放/上下曲(164/165/163/19) -> 捕获 + 日志 + 消费,不路由(媒体会话落地后转活跃会话)。
|
||||
@@ -50,8 +53,12 @@
|
||||
#include <sys/mman.h>
|
||||
#include <poll.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include "meow_ipc.h" /* MSG_AUDIO_VOLUME/MSG_ACK/帧格式(音量收编 v2:首选 audiod 权威) */
|
||||
|
||||
/* device-verified: VSCREENINFO=0x4600, FSCREENINFO=0x4602 (do not swap) */
|
||||
#define FBIOGET_VSCREENINFO 0x4600
|
||||
@@ -214,6 +221,14 @@ static void write_brightness(int val)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* settings.conf 路径(缺省 /usr/data/meow/settings.conf;env MEOW_SETTINGS_FILE 覆盖,
|
||||
* 供宿主测试隔离——与 audiod MEOW_AUDIO_SETTINGS 同款测试钩子,真机无 env 走默认)。 */
|
||||
static const char *wd_settings_path(void)
|
||||
{
|
||||
const char *e = getenv("MEOW_SETTINGS_FILE");
|
||||
return (e && e[0]) ? e : MEOW_SETTINGS_FILE;
|
||||
}
|
||||
|
||||
/* M6.23:亮屏恢复亮度以**用户设置**为准(/usr/data/meow/settings.conf 的 display.brightness),
|
||||
* 而非 wd_saved_bri 快照——该快照可能被污染:panel OFF 前 read_brightness() 可能读到 launcher
|
||||
* 先写好的 0(launcher meow_panel_off 已 write_brightness(0)),`wd_saved_bri=(br>0)?br:60` 便落到
|
||||
@@ -225,7 +240,7 @@ static void write_brightness(int val)
|
||||
* → 返回 -1,调用方回退 wd_saved_bri(保持旧行为,防开机竞态)。 */
|
||||
static int wd_settings_brightness(void)
|
||||
{
|
||||
FILE *f = fopen(MEOW_SETTINGS_FILE, "r");
|
||||
FILE *f = fopen(wd_settings_path(), "r");
|
||||
if (!f) return -1;
|
||||
int b = 101; /* display.brightness 默认(与 launcher 设置表同值,键缺失时 clamp→100) */
|
||||
int mn = 1; /* display.brightness_min 默认(极暗但可见;键缺失时保底) */
|
||||
@@ -372,7 +387,7 @@ static int wd_vol_step = 1; /* 跳步 */
|
||||
static void wd_vol_load(void)
|
||||
{
|
||||
wd_vol = 60; wd_vol_max = 100; wd_vol_step = 1;
|
||||
FILE *f = fopen(MEOW_SETTINGS_FILE, "r");
|
||||
FILE *f = fopen(wd_settings_path(), "r");
|
||||
if (!f) { wd_log("vol: no settings, default %d", wd_vol); return; }
|
||||
char buf[128];
|
||||
while (fgets(buf, sizeof buf, f)) {
|
||||
@@ -391,13 +406,17 @@ static void wd_vol_load(void)
|
||||
wd_log("vol: loaded volume=%d max=%d step=%d", wd_vol, wd_vol_max, wd_vol_step);
|
||||
}
|
||||
|
||||
/* 写真实 DAC(CS43198, numid 1/2, 0-255),与 launcher meow_dac_vol_write 同路径。 */
|
||||
/* 写真实 DAC(CS43198, numid 1/2, 0-255),与 launcher meow_dac_vol_write 同路径。
|
||||
* ⚠️ 音量收编 v2 兜底函数:仅 audiod 未起(HibyOS/开机早期)时由 wd_vol_adj 回退调用;
|
||||
* MeowOS 常态一律走 wd_audiod_set_volume(audiod 唯一权威,防多写者漂移)。
|
||||
* 锥度为定案平方锥度(与 audiod dac_vol_set 同款,勿改语义:CS43198=衰减量,0 最响/255 静音)。 */
|
||||
static void wd_vol_write(int pct)
|
||||
{
|
||||
int t = 100 - pct, dac;
|
||||
if (pct <= 0) dac = 255; /* 真静音(DS1039:255=-127.5dB) */
|
||||
else dac = t * t * 192 / 10000; /* 感知平方锥度:dB 衰减=(1-pct)^2×96dB */
|
||||
if (dac > 255) dac = 255; if (dac < 0) dac = 0; /* CS43198=衰减量(0最响255静音)+平方锥度(听感线性) */
|
||||
if (dac > 255) dac = 255;
|
||||
if (dac < 0) dac = 0; /* CS43198=衰减量(0最响255静音)+平方锥度(听感线性) */
|
||||
char cmd[160];
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"amixer -c 0 cset numid=1 %d >/dev/null 2>&1; amixer -c 0 cset numid=2 %d >/dev/null 2>&1",
|
||||
@@ -406,14 +425,97 @@ static void wd_vol_write(int pct)
|
||||
wd_log("DAC vol -> L/R=%d (pct %d)", dac, pct);
|
||||
}
|
||||
|
||||
/* ---- 音量收编 v2(FUTURE_AUDIO 事项三):首选 audiod 权威 MSG_AUDIO_VOLUME ----
|
||||
* watchdog 为 per-App 小进程,audiod sock 0666 无鉴权可直接连。一次性短连接(按键 rare,
|
||||
* 无常驻连接/陈旧态负担):非阻塞 connect + poll 300ms,SO_SNDTIMEO/RCVTIMEO 1s,发 i32 pct
|
||||
* 等 MSG_ACK。audiod 侧已异步化(末值去抖,ACK=已应用+已持久化),正常 <<1s 返回。
|
||||
* 返回 0=audiod 已受理(DAC 写+持久化均由 audiod 完成,本进程不再写 settings 防双写);
|
||||
* -1=audiod 缺席/失败(调用方回退 wd_vol_write 本地直写 + wd_vol_save 本地持久化)。 */
|
||||
#define WD_AUD_SOCK_DEFAULT "/usr/data/meow_audio.sock" /* 同 audiod AUD_SOCK_DEFAULT */
|
||||
#define WD_AUD_CONN_TMO_MS 300
|
||||
#define WD_AUD_IO_TMO_MS 1000
|
||||
|
||||
static const char *wd_aud_sock(void)
|
||||
{
|
||||
const char *e = getenv("MEOW_AUDIO_SOCK"); /* 与 SDK sock_path() 同款 env(宿主测覆盖) */
|
||||
return (e && e[0]) ? e : WD_AUD_SOCK_DEFAULT;
|
||||
}
|
||||
|
||||
static int wd_wr_all(int fd, const void *p, size_t n)
|
||||
{
|
||||
const uint8_t *b = p; size_t o = 0;
|
||||
while (o < n) { ssize_t r = write(fd, b + o, n - o); if (r < 0) { if (errno == EINTR) continue; return -1; } o += (size_t)r; }
|
||||
return 0;
|
||||
}
|
||||
static int wd_rd_all(int fd, void *p, size_t n)
|
||||
{
|
||||
uint8_t *b = p; size_t o = 0;
|
||||
while (o < n) { ssize_t r = read(fd, b + o, n - o); if (r < 0) { if (errno == EINTR) continue; return -1; } if (r == 0) return -1; o += (size_t)r; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wd_audiod_set_volume(int pct)
|
||||
{
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0) return -1;
|
||||
int fl = fcntl(fd, F_GETFL, 0);
|
||||
if (fl >= 0) fcntl(fd, F_SETFL, fl | O_NONBLOCK);
|
||||
struct sockaddr_un a;
|
||||
memset(&a, 0, sizeof a);
|
||||
a.sun_family = AF_UNIX;
|
||||
snprintf(a.sun_path, sizeof a.sun_path, "%s", wd_aud_sock());
|
||||
int r = connect(fd, (struct sockaddr *)&a, sizeof a);
|
||||
if (r < 0 && errno == EINPROGRESS) {
|
||||
struct pollfd p;
|
||||
p.fd = fd; p.events = POLLOUT; p.revents = 0;
|
||||
if (poll(&p, 1, WD_AUD_CONN_TMO_MS) > 0) {
|
||||
int err = 0;
|
||||
socklen_t el = sizeof err;
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &el) == 0 && err != 0) { errno = err; r = -1; }
|
||||
} else {
|
||||
r = -1; /* 超时/错误 */
|
||||
}
|
||||
}
|
||||
if (r < 0) { close(fd); return -1; }
|
||||
if (fl >= 0) fcntl(fd, F_SETFL, fl); /* 回阻塞模式;读写超时由 SO_*TIMEO 兜底 */
|
||||
struct timeval tv;
|
||||
tv.tv_sec = WD_AUD_IO_TMO_MS / 1000; tv.tv_usec = (WD_AUD_IO_TMO_MS % 1000) * 1000;
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
|
||||
/* 发 MSG_AUDIO_VOLUME(i32 pct);req_id 任意(一次性连接单请求) */
|
||||
uint8_t frame[MEOW_IPC_HDR_LEN + sizeof(int32_t)];
|
||||
uint32_t magic = MEOW_IPC_MAGIC, flen = sizeof(int32_t), freq = 1;
|
||||
uint16_t ver = MEOW_IPC_VERSION, type = MSG_AUDIO_VOLUME;
|
||||
memcpy(frame + 0, &magic, 4);
|
||||
memcpy(frame + 4, &ver, 2);
|
||||
memcpy(frame + 6, &type, 2);
|
||||
memcpy(frame + 8, &freq, 4);
|
||||
memcpy(frame + 12, &flen, 4);
|
||||
int32_t p32 = pct;
|
||||
memcpy(frame + MEOW_IPC_HDR_LEN, &p32, sizeof p32);
|
||||
if (wd_wr_all(fd, frame, sizeof frame) != 0) { close(fd); return -1; }
|
||||
/* 等 MSG_ACK(有界:RCVTIMEO;audiod 异步执行点应用后回 ACK) */
|
||||
uint8_t hdr[MEOW_IPC_HDR_LEN];
|
||||
if (wd_rd_all(fd, hdr, sizeof hdr) != 0) { close(fd); return -1; }
|
||||
uint32_t rmagic, rlen;
|
||||
uint16_t rver, rtype;
|
||||
memcpy(&rmagic, hdr, 4); memcpy(&rver, hdr + 4, 2); memcpy(&rtype, hdr + 6, 2); memcpy(&rlen, hdr + 12, 4);
|
||||
if (rmagic != MEOW_IPC_MAGIC || rver != MEOW_IPC_VERSION || rtype != MSG_ACK || rlen > 64) { close(fd); return -1; }
|
||||
uint8_t pl[64];
|
||||
if (rlen && wd_rd_all(fd, pl, rlen) != 0) { close(fd); return -1; }
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* M2.92+ 修复(真机实证 settings.conf 被毁):旧版 O_TRUNC 整文件重写只剩 4 行 ——
|
||||
* 抹掉全部其它设置;与其它写者交错还叠出重复 audio.volume 行、丢 volume_max/step。
|
||||
* 改为读改写单键(流式拷贝、命中行全部改写去重、缺失末尾追加、rename 原子替换),
|
||||
* 与 SDK meow_ui_vol_set 同款语义。 */
|
||||
static void wd_vol_save(void)
|
||||
{
|
||||
system("mkdir -p /usr/data/meow 2>/dev/null");
|
||||
const char *path = MEOW_SETTINGS_FILE;
|
||||
const char *path = wd_settings_path();
|
||||
if (strcmp(path, MEOW_SETTINGS_FILE) == 0) /* 仅默认路径补目录(env 覆盖=宿主测,目录自备) */
|
||||
system("mkdir -p /usr/data/meow 2>/dev/null");
|
||||
char tmp[300];
|
||||
snprintf(tmp, sizeof tmp, "%s.tmp", path);
|
||||
FILE *in = fopen(path, "r");
|
||||
@@ -490,7 +592,9 @@ static int wd_jack_debounce(void)
|
||||
(now_ms() - wd_jack_changed_at < (unsigned long long)WD_JACK_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
/* 音量步进:+1/-1(每按下边沿一次;clamp 到极大/最小)。 */
|
||||
/* 音量步进:+1/-1(每按下边沿一次;clamp 到极大/最小)。
|
||||
* 音量收编 v2:首选 audiod 权威(IPC;DAC 写+持久化 audiod 完成);audiod 缺席才本地
|
||||
* amixer 直写 + 本地持久化兜底(wd_vol 本地缓存仅作步进基数,两路都维护)。 */
|
||||
static void wd_vol_adj(int dir)
|
||||
{
|
||||
int target = wd_vol + dir * wd_vol_step;
|
||||
@@ -498,9 +602,13 @@ static void wd_vol_adj(int dir)
|
||||
if (target > wd_vol_max) target = wd_vol_max;
|
||||
if (target == wd_vol) { wd_log("volume %s at limit (%d)", dir > 0 ? "UP" : "DOWN", wd_vol); return; }
|
||||
wd_vol = target;
|
||||
wd_vol_write(wd_vol);
|
||||
if (wd_audiod_set_volume(wd_vol) == 0) {
|
||||
wd_log("volume %s -> %d (via audiod)", dir > 0 ? "UP" : "DOWN", wd_vol);
|
||||
return;
|
||||
}
|
||||
wd_vol_write(wd_vol); /* 兜底:仅 audiod 未起(HibyOS/开机早期) */
|
||||
wd_vol_save();
|
||||
wd_log("volume %s -> %d", dir > 0 ? "UP" : "DOWN", wd_vol);
|
||||
wd_log("volume %s -> %d (local amixer fallback, audiod absent)", dir > 0 ? "UP" : "DOWN", wd_vol);
|
||||
}
|
||||
|
||||
static void handle_touch(int immersive, int app_pid,
|
||||
|
||||
Reference in new issue
Block a user