diff --git a/patch_v2/meow_launcherd/font_theme.c b/patch_v2/meow_launcherd/font_theme.c index 95f6c02..00b9837 100644 --- a/patch_v2/meow_launcherd/font_theme.c +++ b/patch_v2/meow_launcherd/font_theme.c @@ -474,7 +474,7 @@ static void font_tier_marker(const char *charset, int glyph_count, char *out, in * 输出:label=显示名 ` (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,16 +506,20 @@ 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,不硬失败;该套仍标记可选。 */ - 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); - else if (jsha_png[0] && !font_sha_eq(apng, jsha_png)) - logmsg("fonts: '%s/%s%s%s' WARN sha256_png 不匹配(仍可选)", family, wt, tsep, tiernm); - if (font_sha256_file(ipath, aidx, sizeof aidx) != 0) - 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); + /* 完整性校验:仅 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); + else if (jsha_png[0] && !font_sha_eq(apng, jsha_png)) + logmsg("fonts: '%s/%s%s%s' WARN sha256_png 不匹配(仍可选)", family, wt, tsep, tiernm); + if (font_sha256_file(ipath, aidx, sizeof aidx) != 0) + 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) { /* 两级(旧结构向后兼容)://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); } diff --git a/patch_v2/meow_launcherd/main_menu.c b/patch_v2/meow_launcherd/main_menu.c index 95724d9..003a8fb 100644 --- a/patch_v2/meow_launcherd/main_menu.c +++ b/patch_v2/meow_launcherd/main_menu.c @@ -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///,填充「字体文件」下拉 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/// 并打印 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], diff --git a/patch_v2/meow_launcherd/meow_launcher_internal.h b/patch_v2/meow_launcherd/meow_launcher_internal.h index 37925d2..70844bf 100644 --- a/patch_v2/meow_launcherd/meow_launcher_internal.h +++ b/patch_v2/meow_launcherd/meow_launcher_internal.h @@ -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); diff --git a/patch_v2/meow_launcherd/meow_launcherd b/patch_v2/meow_launcherd/meow_launcherd index 87680be..958abf0 100755 Binary files a/patch_v2/meow_launcherd/meow_launcherd and b/patch_v2/meow_launcherd/meow_launcherd differ diff --git a/patch_v2/meow_launcherd/net.c b/patch_v2/meow_launcherd/net.c index 07dcaed..6ec1d05 100644 --- a/patch_v2/meow_launcherd/net.c +++ b/patch_v2/meow_launcherd/net.c @@ -662,23 +662,50 @@ static int g_net_scan_n = 0; static int g_net_bt_n = 0; -/* 刷新网络信息缓存(进入设置页 / 网络动作后调用;含一次 WiFi 扫描触发) */ +/* ---- 设置页异步网络刷新(进设置不再在入口同步跑子进程查询)---- + * 背景:进设置页此前在入口同步跑 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); + else snprintf(g_net_ssid, sizeof g_net_ssid, "已连接"); + } else { + snprintf(g_net_ssid, sizeof g_net_ssid, "未连接"); + } + 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) { - 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); - else snprintf(g_net_ssid, sizeof g_net_ssid, "已连接"); - } 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); /* 附近(已配对+扫描发现) */ + 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 逐步骤填充 */ } diff --git a/patch_v2/meow_launcherd/settings_page.c b/patch_v2/meow_launcherd/settings_page.c index fedff04..ea613a7 100644 --- a/patch_v2/meow_launcherd/settings_page.c +++ b/patch_v2/meow_launcherd/settings_page.c @@ -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///,刷新「字体文件」下拉。 - * 进设置时卡通常在位;此步只枚举/校验,不加载(加载由 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];