launcher: 进设置页不再同步跑串行网络 popen 与逐套字体 sha256(点设置卡≥5s 修复)

- 设置页入口 s_net_sync_from_sys() 改为 toggle 同步(快)+异步 s_net_refresh_kick();
  wifi/bt 状态与列表由 run_settings_page 主循环逐步骤 s_net_refresh_pump() 填充
  (每步一个带超时 popen、~150ms 一步),draw 用 g_net_* 缓存,数据变化即 need_paint
  → 入口不再被 wpa_cli/bluetoothctl/hcitool 5 条串行 popen(各 1.2~2.5s 有界超时)拖住。
- 进设置页字体重扫 meow_font_scan_presets(0) 跳过逐套 sha256(gbk/full 套数 MB,
  逐套双 sha256 真机耗数秒,入口卡顿主因之一);完整性校验保留给启动/热插拔全量(verify=1)。
- s_net_refresh() 保留同步语义(kick+drain) 供通知中心等调用方;WiFi/BT 子页返回、
  网络下拉后改 kick(由主循环承担异步填充)。
- 设置入口加毫秒级分段日志(font rescan / net toggle-sync+kick / page shown)供真机取证。
- 交叉 -Wall -Wextra 0 warning;launcher 宿主测试全 PASS。launcher md5 fbc78c62
This commit is contained in:
AskaEth committed 2026-09-02 03:18:36 +08:00
1 parent 0294553096
commit 41427fdcb3
6 files changed
+87 -31

No files matched your search

+14 -8
View File
@@ -474,7 +474,7 @@ static void font_tier_marker(const char *charset, int glyph_count, char *out, in
* 输出:label=显示名 `<name> <Weight>(common≈4k)`(如 `MiSans Regular(common≈4k)`);
* charset/glyph_count=档位信息;wtout=weight slug(缺省 "regular")。 */
static int meow_font_probe_weight(const char *dirpath, const char *family, const char *weight,
const char *tier_dir,
const char *tier_dir, int verify_sha,
char *label, int llen,
char *charset, int clen, int *glyph_count,
char *wtout, int wtlen, char *nameout, int namelen)
@@ -506,7 +506,10 @@ static int meow_font_probe_weight(const char *dirpath, const char *family, const
snprintf(label, llen, "%s %s(%s)", name[0] ? name : family, wd, marker);
if (charset) snprintf(charset, clen, "%s", tier);
if (glyph_count) *glyph_count = gc;
/* 完整性校验:仅 WARN,不硬失败;该套仍标记可选。 */
/* 完整性校验:仅 WARN,不硬失败;该套仍标记可选。
* M3:verify_sha=0(进设置页重扫)跳过逐套 sha256sum(gbk/full 套数 MB,逐套双 sha256
* 真机耗数秒,入口卡顿主因之一);完整性校验保留给启动全量扫描(verify_sha=1)。 */
if (verify_sha) {
char apng[80] = "", aidx[80] = "";
if (font_sha256_file(ppath, apng, sizeof apng) != 0)
logmsg("fonts: '%s/%s%s%s' sha256(png) 不可用,跳过校验", family, wt, tsep, tiernm);
@@ -516,6 +519,7 @@ static int meow_font_probe_weight(const char *dirpath, const char *family, const
logmsg("fonts: '%s/%s%s%s' sha256(idx) 不可用,跳过校验", family, wt, tsep, tiernm);
else if (jsha_idx[0] && !font_sha_eq(aidx, jsha_idx))
logmsg("fonts: '%s/%s%s%s' WARN sha256_idx 不匹配(仍可选)", family, wt, tsep, tiernm);
}
logmsg("fonts: add '%s/%s%s%s' (%s) tier=%s glyph_count=%d", family, wt, tsep, tiernm, label, tier, gc);
return 1;
}
@@ -637,7 +641,7 @@ static int font_presets_add(const char *family, const char *weight, const char *
* 选库)与 meow_font_reload_multifont 在运行期持续读 font_presets_n,清空会造成大字库
* 档位退化(red line「保持档位/多字体行为」)。如需「零驻留」,须把这几个核心路径改为
* 直接读 index(较大重构,超出本批边界,留待后续)。 */
void meow_font_scan_presets_root(const char *card_root)
void meow_font_scan_presets_root(const char *card_root, int verify_sha)
{
font_presets_n = 0;
font_presets[0] = "MeowOS/fonts/default/regular/font.png"; /* 默认字库 = MeowOS/fonts/default/regular */
@@ -684,7 +688,7 @@ void meow_font_scan_presets_root(const char *card_root)
char label[96] = "", cs[8] = ""; int gc = 0; char wt[32] = "", nm[64] = "";
if (access(pngcheck, R_OK) == 0) {
/* 两级(旧结构向后兼容):<family>/<weight>/font.png,tier 读 font.json charset。 */
if (meow_font_probe_weight(dirpath, de->d_name, we->d_name, NULL,
if (meow_font_probe_weight(dirpath, de->d_name, we->d_name, NULL, verify_sha,
label, sizeof label, cs, sizeof cs, &gc,
wt, sizeof wt, nm, sizeof nm) == 0)
continue; /* 缺组件/损坏 → 跳过该套 */
@@ -702,7 +706,7 @@ void meow_font_scan_presets_root(const char *card_root)
strcmp(te->d_name, "full")) continue;
char tpath[420];
snprintf(tpath, sizeof tpath, "%s/%s", dirpath, te->d_name);
if (meow_font_probe_weight(tpath, de->d_name, we->d_name, te->d_name,
if (meow_font_probe_weight(tpath, de->d_name, we->d_name, te->d_name, verify_sha,
label, sizeof label, cs, sizeof cs, &gc,
wt, sizeof wt, nm, sizeof nm) == 0)
continue; /* 缺组件/损坏 → 跳过该 tier 套 */
@@ -728,10 +732,12 @@ void meow_font_scan_presets_root(const char *card_root)
}
/* 设备默认卡根扫描(等价现状:无卡时 opendir 失败 → 仅默认字体)。 */
void meow_font_scan_presets(void)
/* 设备默认卡根扫描(等价现状:无卡时 opendir 失败 → 仅默认字体)。
* verify_sha=1:启动/热插拔全量扫描(含逐套 sha256 完整性校验)。
* verify_sha=0:进设置页重扫(只枚举+读 font.json+落 index,跳过 sha256 —— 入口不许卡数秒)。 */
void meow_font_scan_presets(int verify_sha)
{
meow_font_scan_presets_root("/usr/data/mnt/sd_0");
meow_font_scan_presets_root("/usr/data/mnt/sd_0", verify_sha);
}
+4 -4
View File
@@ -996,7 +996,7 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
unsigned long long fsig = fonts_dir_sig();
if (fsig != fonts_sig) {
fonts_sig = fsig;
meow_font_scan_presets();
meow_font_scan_presets(1); /* 目录签名变化:全量扫描(含 sha256 校验) */
}
}
if (was_nocard || state != 0 || napps == 0) {
@@ -1801,13 +1801,13 @@ int main(int argc, char **argv)
settings_load(); /* M2.11:读系统设置(audio.volume 等),供音量/状态栏使用 */
/* M2.6:启动扫描一次 TF 卡 MeowOS/fonts/<family>/<weight>/,填充「字体文件」下拉 preset。
* 无卡/无字库目录 → 仅默认字体(等价现状)。进设置页时 run_settings_page 会再扫一次。 */
meow_font_scan_presets();
* 无卡/无字库目录 → 仅默认字体(等价现状)。进设置页时 run_settings_page 会再扫一次(verify=0)。 */
meow_font_scan_presets(1); /* 启动全量扫描:含逐套 sha256 完整性校验 */
if (fontscan_root) {
/* M2.6 测试钩子:扫描指定卡根下的 MeowOS/fonts/<family>/<weight>/ 并打印 preset(qemu/宿主可测)。
* 用于验证 font.json 解析(含 weight)/三件套/缺件跳过/sha 校验 + preset 动态化逻辑。 */
meow_font_scan_presets_root(fontscan_root);
meow_font_scan_presets_root(fontscan_root, 1); /* 测试钩子:全量含 sha256 */
printf("fonts=%d\n", font_presets_n);
for (int i = 0; i < font_presets_n; i++)
printf(" %d %s -> %s (fam=%s wt=%s)\n", i, font_preset_labels[i], font_presets[i],
@@ -721,8 +721,8 @@ int meow_font_effective_tier(int app_tier);
int meow_font_ensure(void);
void meow_font_reload_multifont(void);
int meow_font_resolve_path(const char *ref, char *out, int olen);
void meow_font_scan_presets(void);
void meow_font_scan_presets_root(const char *card_root);
void meow_font_scan_presets(int verify_sha);
void meow_font_scan_presets_root(const char *card_root, int verify_sha);
int meow_ipc_init(void);
void meow_ipc_process(void);
/* M4:IPC 连接存活查询(熔断广播投递前判连接未断;util.c ipc_conns 表查 fd)。 */
@@ -783,6 +783,10 @@ int s_net_get(const srow_t *r, char *buf, int len);
void s_net_open(const srow_t *r);
void s_net_refresh(void);
void s_net_sync_from_sys(void);
/* M3:设置页异步网络刷新 —— kick 重置步骤机并触发扫描(非阻塞);pump 每步一个
* 有界 popen,返回 1=数据可能更新(调用方重绘)。run_settings_page 主循环逐步骤驱动。 */
void s_net_refresh_kick(void);
int s_net_refresh_pump(void);
void s_net_toggle_bt(int on);
void s_net_toggle_wifi(int on);
Binary file not shown.
+39 -11
View File
@@ -662,9 +662,28 @@ static int g_net_scan_n = 0;
static int g_net_bt_n = 0;
/* 刷新网络信息缓存(进入设置页 / 网络动作后调用;含一次 WiFi 扫描触发) */
void s_net_refresh(void)
/* ---- 设置页异步网络刷新(进设置不再在入口同步跑子进程查询)----
* 背景:进设置页此前在入口同步跑 s_net_refresh()——wpa_cli/bluetoothctl/hcitool 逐条
* popen(各自带 1.2~2.5s 有界超时),5 条串行叠加达数秒,真机表现为「点设置卡 ≥5s」。
* 修法:入口只 draw + 触发扫描(快),wifi/bt 状态与列表改由 run_settings_page 主循环
* 逐步骤 pump(每步一个带超时 popen,数据变化即 need_paint)。s_net_refresh() 保留同步
* 语义(kick + drain)供需要立即结果的调用方(通知中心等)使用。
* 步骤:1=SSID 2=已保存 3=附近WiFi 4=蓝牙角色 5=附近蓝牙(各写 g_net_* 与 g_bt_mode)。 */
static int g_net_rstep = 0; /* 0=idle;1..N=步骤机位置 */
void s_net_refresh_kick(void)
{
net_wifi_scan_trigger(); /* 异步发起扫描(wpa_cli scan 快返回) */
net_bt_scan_trigger(); /* 异步发起 BT 附近扫描(& 立即返回) */
g_net_rstep = 1;
}
int s_net_refresh_pump(void)
{
meow_net_t tmp[S_NET_MAX];
switch (g_net_rstep) {
case 1:
g_net_rstep = 2;
if (wlan_connected()) {
char ss[64]; net_wifi_ssid(ss, sizeof ss);
if (ss[0]) snprintf(g_net_ssid, sizeof g_net_ssid, "已连接: %s", ss);
@@ -672,13 +691,21 @@ void s_net_refresh(void)
} else {
snprintf(g_net_ssid, sizeof g_net_ssid, "未连接");
}
net_wifi_scan_trigger(); /* 异步发起扫描,稍后附近/计数更接近真实 */
net_bt_scan_trigger(); /* M2.40:异步发起蓝牙附近扫描(写 /tmp 缓存,不阻塞) */
bt_role_refresh(1); /* M2.48:进入设置/网络动作时立即重探蓝牙角色,本行/状态栏最新 */
meow_net_t tmp[S_NET_MAX];
g_net_saved_n = net_wifi_saved(tmp, S_NET_MAX);
g_net_scan_n = net_wifi_scan(tmp, S_NET_MAX);
g_net_bt_n = net_bt_scan(tmp, S_NET_MAX); /* 附近(已配对+扫描发现) */
return 1;
case 2: g_net_rstep = 3; g_net_saved_n = net_wifi_saved(tmp, S_NET_MAX); return 1;
case 3: g_net_rstep = 4; g_net_scan_n = net_wifi_scan(tmp, S_NET_MAX); return 1;
case 4: g_net_rstep = 5; bt_role_refresh(1); return 1; /* 蓝牙角色 → g_bt_mode */
case 5: g_net_rstep = 0; g_net_bt_n = net_bt_scan(tmp, S_NET_MAX); return 1;
default: return 0;
}
}
/* 刷新网络信息缓存(同步:kick + 排空全部异步步骤;需要立即结果的调用方用)。
* 进设置页走 s_net_sync_from_sys()(非阻塞:toggle 同步 + kick,由主循环 pump)。 */
void s_net_refresh(void)
{
s_net_refresh_kick();
while (s_net_refresh_pump()) { /* drain: 同步排空所有异步步骤 */ }
}
@@ -734,7 +761,8 @@ void s_net_sync_from_sys(void)
int real = hci_powered() ? 1 : 0;
if (real != cur) meow_settings_set_bool("network.bluetooth_enabled", real);
}
s_net_refresh();
/* 只同步开关(快)+ 异步 kick;状态/列表由 run_settings_page 主循环 pump,绝不阻塞入口。 */
s_net_refresh_kick();
}
@@ -798,6 +826,6 @@ void s_net_open(const srow_t *r)
default:
return;
}
s_net_refresh();
s_net_refresh_kick(); /* 异步刷新;run_settings_page 主循环 pump 逐步骤填充 */
}
+24 -6
View File
@@ -972,10 +972,14 @@ void run_settings_page(void)
int sel = s_first_setting();
int scroll_off = 0;
int H = fb_yres;
unsigned long long t_sets = now_ms(); /* M3 取证:进设置页耗时分段(真机核对用) */
/* M2.6:进设置页扫描一次 TF 卡 MeowOS/fonts/<family>/<weight>/,刷新「字体文件」下拉。
* 进设置时卡通常在位;此步只枚举/校验,不加载(加载由 meow_font_ensure 按 font.file 决定)。 */
meow_font_scan_presets();
* 进设置时卡通常在位;此步只枚举/校验,不加载(加载由 meow_font_ensure 按 font.file 决定)。
* M3:verify=0 —— 跳过逐套 sha256 校验(gbk 套 6.8MB 级,逐套双 sha256 真机耗数秒),
* 只枚举+读 font.json+落 index,入口不再被 sha256sum 拖住;完整性校验留给启动全量扫描。 */
meow_font_scan_presets(0);
logmsg("settings entry: font rescan %llums", now_ms() - t_sets);
struct keypoll kp_power, kp_keys;
kp_open(&kp_power, DEV_POWER); kp_open(&kp_keys, DEV_KEYS);
@@ -995,6 +999,7 @@ void run_settings_page(void)
unsigned long long last_tick = now_ms();
unsigned long long last_act = now_ms(); /* 最近一次交互时间(自动息屏用) */
int after_modal = 0; /* 选择器子对话框刚关闭:其全屏 dim 覆盖过状态栏,需整帧重绘还原 */
unsigned long long net_refresh_pump_at = 0; /* M3:异步网络刷新下一推进时刻(0=立即) */
/* 触摸拖动滑条状态 */
int td = 0, td_ok = 0, tdx = -1, tdy = -1, tlx = -1, tly = -1;
@@ -1014,10 +1019,15 @@ void run_settings_page(void)
int pwr_suppress_click = 0; /* 菜单刚关闭:松开不得误判单击熄屏(M2.34 同款) */
/* 首次全帧绘制 */
s_net_sync_from_sys(); /* M2.39:WiFi/蓝牙开关行同步真实硬件态 + 刷新网络信息缓存 */
/* M2.39/M3:开关行同步真实硬件态(快)+ 异步 kick 网络刷新 —— 不再在入口同步跑
* wpa_cli/bluetoothctl 串行 popen(真机 ≥5s 卡顿根因);状态/列表由下方主循环逐步骤
* s_net_refresh_pump() 填充,draw 用缓存(g_net_*),数据变化即 need_paint。 */
s_net_sync_from_sys();
logmsg("settings entry: net toggle-sync+kick %llums", now_ms() - t_sets);
scroll_off = s_clamp_scroll(sel, scroll_off);
draw_settings_page(sel, scroll_off);
meow_dirty_full(); meow_ui_flush();
logmsg("settings entry: page shown in %llums", now_ms() - t_sets);
for (;;) {
unsigned long long now = now_ms();
@@ -1072,6 +1082,14 @@ void run_settings_page(void)
continue;
}
/* ---- M3:异步网络刷新(每 ~150ms 推进一步,每步一个有界 popen)----
* 入口已同步 draw(用 g_net_* 缓存),此处逐步填充 SSID/已保存/附近/蓝牙角色,
* 数据变化则 need_paint=1 让行值即时刷新,绝不在某一同步调用里连续跑数条 popen。 */
if (now >= net_refresh_pump_at) {
net_refresh_pump_at = now + 150;
if (s_net_refresh_pump()) need_paint = 1;
}
/* ---- 按键 ---- */
kp_poll(&kp_power, NULL, NULL); kp_poll(&kp_keys, NULL, NULL);
int vold = 0, volu = 0, play = 0, pwr = 0;
@@ -1277,9 +1295,9 @@ void run_settings_page(void)
* M2.76:WiFi/蓝牙升级为独立子页面 → 点开进 run_wifi_page/
* run_bt_page(阻塞,内部自开 fds;返回后仍须排空本页 tfd)。 */
after_modal = 1;
if (r->net_list == NET_LIST_WIFI_PAGE) { run_wifi_page(); s_net_refresh(); }
else if (r->net_list == NET_LIST_BT_PAGE) { run_bt_page(); s_net_refresh(); }
else if (r->net_list == NET_LIST_PIN_PAGE) { run_lock_settings_page(); s_net_refresh(); }
if (r->net_list == NET_LIST_WIFI_PAGE) { run_wifi_page(); s_net_refresh_kick(); }
else if (r->net_list == NET_LIST_BT_PAGE) { run_bt_page(); s_net_refresh_kick(); }
else if (r->net_list == NET_LIST_PIN_PAGE) { run_lock_settings_page(); s_net_refresh_kick(); }
else s_net_open(r);
if (tfd >= 0) {
unsigned char e[16];