Files
MeowOS-For-R3P2/docs/MEOWOS_SPEC_REF.md
T

309 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MeowOS 核心规范速查(MEOWOS_SPEC_REF)
> 单一速查来源。常量/路径**照抄原文**;矛盾处单列「已知矛盾/待确认」。
> 各条末尾 `[源:XX.md]` 标注出处。
---
## 1. 文件系统路径
### 1.1 板载(NAND rootfs / /data)
- 设置持久化:**板载** `/usr/data/meow/settings.conf`(UBIFS,小文件 <10KB,跨换卡保留)`[SYSTEM_SETTINGS §2][MEOWOS_API §3]`
- `/etc/meowos_version`:版本唯一来源(launcher 运行时 `load_meowos_version` 读;`MEOWOS_VERSION` 宏仅作 dev 占位兜底)`[DEV_NOTES #4]`
- `/tmp`:tmpfs,开机清空;开机模式标记 `/tmp/meow_boot_mode`、电源菜单 `/tmp/meow_power_menu{,_active}`、app 沉浸 `/tmp/meowapp_state` `[BOOT_SELECTOR §1][KEY_CONTROL §9][APPS §3.5]`
- 日志启动缓冲 `/tmp/meow_boot.log`(256KB 滚动,卡出现后自动迁卡)`[APPS §4.5]`
- IPC socket:`/usr/data/meow_ipc.sock`(AF_UNIX SOCK_STREAM,0666,backlog 4)`[FRAMEWORK_DESIGN §1][WORK_STATE]`
- seccomp/分区(勿写):mtd0=uboot mtd1=kernel mtd2=rootfs mtd3=kernel2 mtd4=rootfs2 mtd5=ota(8M 标记) mtd6=userdata `[WORK_STATE]`
### 1.2 TF 卡(挂载点 `/usr/data/mnt/sd_0`,exFAT)
```
/usr/data/mnt/sd_0/
├── Music/ # 播放器标准索引目录
├── MeowData/<pkg>/{data,cache} # 应用专属数据(exFAT 无软链,用 env 注入)
├── MeowAPPs/ # 应用(<package>=app.json.package=目录名;app.json+二进制+资源, fonts/, backgrounds/;日志已入 MeowOS/logs[源:审计 2026-08-30])
├── MeowOpt/ # 板载外部工具/二进制(如 mdnsd/,卡上加载,拔卡降级不崩)`[DEV_NOTES][meow_svcd.md]`
└── MeowOS/ # MeowOS 专属(一切非必要文件)
├── backups/settings/setting.bak # 设置导出默认路径
├── fonts/<family>/ # 多字体库(每套一个子目录,见 §5.2)
│ ├── font.png # 预渲染灰度 PNG(bit depth 4|8,gen/gen_font.py 产物)
│ ├── font.idx # 索引(MFNI v2,gen/gen_font.py 产物)
│ └── font.json # 元数据 + sha256 完整性校验(schema 见 §5.2)
├── logs/ # 系统日志 meow_<bootts>.log + apps/...(见 §3 日志)
├── notifications/(转储区,保留最新 10MB,不被电源事件清)
├── opt/{bin,nyai,sources.list}, lib/, tools/
└── themes/charging/<id>/ # 充电屏主题(theme.json manifest)
```
`[TF_CARD_LAYOUT §1][APPS 附录][NOTIFICATION_SYSTEM §5]`
- 环境注入(launcher 每次启动 app 前):`MEOW_DATA_DIR`/`MEOW_CACHE_DIR`/`MEOW_LOG_DIR`/`MEOW_LOG_APP`(app_id=package)/`MEOW_LOG_LEVEL`/`MEOW_ACTIVITY`/`MEOW_CHAIN`;XDG:`XDG_DATA_HOME`/`XDG_CACHE_HOME`/`XDG_CONFIG_HOME`(=MeowData/<pkg>/{data,cache,config})`[APPS 附录 §2][FRAMEWORK_DESIGN 附录 D2]`
### 1.3 板载 vs TF 划分原则(拔卡降级)
- 板载只放**稳定框架+KB 级设置**;日志/字库/媒体等大件一律 TF 卡 `[TF_CARD_LAYOUT §0][SYSTEM_SETTINGS §2]`
- 拔卡:launcher/bootmenu/SSH 不死;应用列表"未插卡"、日志回退内存环、字体回退点阵、opt 不可用——均优雅降级 `[TF_CARD_LAYOUT §3]`
- 关键配置优先板载(无卡系统能跑);转储/日志可降级 → 卡,无卡 /tmp 回退 `[DEV_NOTES #7]`
- rootfs 体积上限:**45,088,768 B(≈45MB)**,回验 0 diff `[BOOT_SELECTOR §1][APPS §6]`
---
## 2. IPC / 接口
### 2.1 launcher↔app env 注入
`MEOW_LOG_DIR`(卡日志目录,无卡不设)/`MEOW_LOG_APP`(app_id=app.json.package,缺省回退目录名)/`MEOW_LOG_LEVEL`(本 app 级别,系统下发)/`MEOW_ACTIVITY`<target>/`MEOW_CHAIN`<id0>;<id1>;...;<top> `[APPS §3.5][APP_LOG_MANAGER §3][FRAMEWORK_DESIGN §3]`
### 2.2 meow_ipc 消息协议(AF_UNIX,全小端 LE)
- 帧头 16B:`magic=0x4D4F5701`('MEOW'|1)/`version=1`/`type`/`req_id`/`len`;`len` 上限 **MEOW_IPC_MAX=4096**;列表编码 `[u16 count]`+NUL 串 `[FRAMEWORK_DESIGN §1]`
- 消息类型:`MSG_HELLO 0x0001↑ / ACK 0x0002↓ / ERR 0x0003↓ / REGISTER 0x0010↑ / SERVICE_OK 0x0011↓ / SERVICE_STOP 0x0012↑ / MSG_NOTIFY 0x0020↑ / NOTIFY_ACK 0x0021↓ / NOTIFY_DISMISS 0x0022↑ / NOTIFY_LIST 0x0023↓ / ACT_DECLARE 0x0030↑ / ACT_QUERY 0x0031↑ / ACT_RESULT 0x0032↓ / NAV 0x0040↑ / SHOW_ACTIVITY 0x0041↓ / SYS 0x00F0↓` `[FRAMEWORK_DESIGN §1]`
- 媒体:`MSG_META`(元数据)、`MSG_PLAYCTL`(cmd 1=播放2=暂停3=上一首4=下一首5=seek)、`MSG_PROGRESS` `[附录 B]`
- IPC 线程**只读帧+解析+入队**;状态变更主循环单写者(eventfd 唤醒,10ms 热键轮询非阻塞排空)`[FRAMEWORK_DESIGN §0][§6]`
### 2.3 watchdog / supervisor 信号
- 应用返回键=**SIGTERM**(1s 后 SIGKILL 兜底);**SIGUSR1 仅**=沉浸左缘滑动手势,不是返回键 `[APPS §3.5]`
- 强杀兜底:应用卡死 = 音量减连按 3 次(间隔 <hotkey_seq_gap)→SIGTERM→0.5s→SIGKILL `[APPS §3.5]`
- 全程禁:`killall hiby_player`/SIGUSR1 发给播放器/走 hiby_player.sh(其 `sleep 1; reboot` 看门狗)/触碰 NAND/recovery_all `[APPS §1.3][WORK_STATE]`
- 播放器信号:SIGSTOP/CONT 安全;SIGTERM 仅运行态(~2s)有效,T 态需先 SIGCONT;SIGKILL 兜底 `[BOOT_SELECTOR §1]`
- supervisor(meow_bootmenu)接管关机/升级:播放器 `exit(0)`→真 poweroff;检测 mtd5=`ota:kernel2`→真 reboot `[WORK_STATE][MIGRATION_AC 无]`
### 2.4 按键信号全局接管(除电源菜单)`[APPS §3.4.1][KEY_CONTROL §1]`
- 红线:**除电源菜单(允许电源=确认、音量=导航)外,所有按键由 MeowOS 全局接管**——任何界面(含 MeowOS 设置页/应用列表/MeowAPP)不得私自定义按键映射;导航走触摸(返回钮/左缘左滑)`[APPS §3.4.1]`
- | 键 | code | 语义 | 阶段 |
|---|---|---|---|
| 电源单击 | 116 | 息屏/亮屏 | ✅ watchdog |
| 电源长按 3s | 116 | 电源菜单(关机/重启/回HibyOS/取消)| ✅ launcher 一处绘制 |
| 电源长按 8s | 116 | 强制关机 | ✅ |
| 音量+ | 115 | 调音量(CS43198)| ✅ |
| 音量− | 114 | 调音量 | ✅ |
| 播放/暂停 | 164 | 活跃媒体会话 | 🔵先抓住 |
| 上一曲 | 165 | 同上 | 🔵先抓住 |
| 下一曲 | 163 | 同上 | 🔵先抓住 |
### 2.5 热键 / 菜单 / 电源菜单 / 音量
- 热键(默认):**按住电源 + 300ms~2.5s 内单击音量减**(`meow.conf hotkey=power_voldown`;历史 `hotkey=seq` 已退役)`[APPS §4.2]`;v6.7 修正窗口下限 **60ms**(见矛盾 §A)
- 电源菜单 5 按钮:关机/重启/回 HibyOS / 取消 /(+「升级模式」按钮)`[WORK_STATE][BOOT_SELECTOR]`
- 音量跳步:`audio.volume_step` int 1-5 默认 **1**;watchdog 每按下边沿一步(无线性渐变)`[KEY_CONTROL §9 偏差2]`
---
## 3. SDK 公共 API(meow_ui.h)—— 以实现定案为准
> 权威签名 = `patch_v2/sdk/meow_ui.h`;MEOW_APP_SDK.md §3-§8 为设计蓝本。
### 3.1 关键常量
- 屏幕:**480×720**,24-bit RGB(`0xRRGGBB`),内部转 RGB565;文本字号 28(标题/状态栏)/20(正文/按钮) `[MEOW_APP_SDK §2]`
- keycode:POWER=116/VOLUMEDOWN=114/VOLUMEUP=115/PLAYPAUSE=164/PREVIOUS=19(注释标 KEY_PREVIOUSSONG,**有疑**)/NEXT=163 `[meow_ui.h][KEY_CONTROL 注:165 才是 prevsong]`
- 事件:`on_key(code,is_down)/on_tap(x,y)/on_swipe(dir,dx,dy)/on_tick/on_swipe_progress(x_start,dx)`;`MEOW_SWIPE_LEFT=0/RIGHT=1/UP=2/DOWN=3` `[meow_ui.h]`
- 主题:`MEOW_THEME_LIGHT/DARK/AUTO`;`meow_theme{bg,fg,accent,dim,font_title=28,font_body=20}` `[meow_ui.h]`
- 控件:`meow_list_source = int (*)(int idx,char *label,int len,void *ctx)`([D2] 定案)`[meow_ui.h]`
- 刷新率:`meow_ui_set_refresh_rate(60/30/15)`/`meow_ui_set_refresh_always_max(1)`/`meow_ui_effective_rate()`/`meow_ui_frames_presented()` `[meow_ui.h §7.1]`
- 状态栏:`meow_ui_set_statusbar(1/0)`/`meow_ui_statusbar_height()`(非全屏=28,全屏=0)/`meow_ui_set_fullscreen(on)`;状态栏高 **MUI_SBAR_H=28**(用户定 40→28,字号随之为 20)`[MIGRATION_AC §11.1][meow_ui.h]`
- 日志:`MEOW_LOG_DEBUG=0/INFO/WARN/ERROR`;`meow_log(lvl,fmt,...)`/`meow_log_set_level`/`meow_log_get_level` `[meow_ui.h §9]`
- 通知:见 §4。
### 3.2 render/控件/图片/输入/IME 签名(关键)
- `meow_ui_init(const meow_ui_opts*)`(opts.width/height,0=自动读 fb)/`meow_ui_shutdown`/`meow_ui_width`(480)/`meow_ui_height`(720)
- 绘制:`meow_ui_clear/put_px/fill_rect/draw_rect/draw_rect_round/fill_rect_alpha(color,alpha 0-255)/flush/flush_region`
- 文本:`meow_ui_text/text_right/text_center(x,y,utf8,size,color)/text_width/text_height`
- 图片:`meow_img_load_file/mem/free/w/h`/`meow_ui_img/scaled/alpha/cover`(stb_image 解 PNG/JPEG/BMP,最近邻缩放,`cover`=居中裁方)
- 控件:`meow_btn_create/slider_create/switch_create/list_create(count,src,ctx)/widget_free/draw/hit`;`meow_slider_set/get`、`meow_switch_set/get`、`meow_btn_pressed`
- IME:`MEOW_IME_ASCII/NUM`;`meow_ime_ctx{mode,buf[256],maxlen,on_change,ctx}`;`meow_ui_text_input`(阻塞)/`_async`/`meow_ime_active`/`meow_ime_text`(仅英文/数字 ASCII;键盘占底 ~300px)
- 生命周期:`meow_ui_run(&ev)`(阻塞)/`meow_ui_request_exit()`;`meow_ui_time_ms()`(单调 ms)
### 3.3 实现定案(相对设计稿)`[MEOW_APP_SDK §12][meow_ui.h]`
- [D1] `meow_ui_opts` 补 width/height;[D2] `meow_list_source` 定案签名;[D3] 内部 `meow_gfx_fill_round/blit_rgba/mark_dirty`(非公共);[D4] 新增 `meow_theme_defaults(mode)`/`meow_theme_current()`;[D5] `on_swipe_progress`+`meow_ui_swipe_hint(x)`+内部 `MEOW_EV_SWIPE_PROGRESS`/`meow_input_inject`;[D6] 状态栏高=40(后续用户定 40→28);[D7] 音量源=settings.conf `audio.volume`;[D8] 蓝牙读 `hciconfig` 30s 缓存;[D9] 状态读取器跑在 `meow_ui_run` 1s 节流(无独立线程);[D10] 全局返回默认语义="APP 未注册 on_swipe 时 SDK 默认退出;已注册交 APP"
- **构建取向(已知设计,非缺陷)**:`build_sdk.sh` 用 `-I../meow_launcherd` 引 `meow_ipc.h`(`meow_notify_ipc.c` 复用共享协议头),故 SDK 编译期依赖 launcher 头、**非独立库**;**运行时无碍** —— App 只链 `meow_ui.a`(含 meow_font.o),不会链入 launcher 符号。SDK 编译依赖 launcher 头属已知设计,勿当作耦合错误。
---
## 4. SDK 之外系统组件
- 通知(SDK `meow_notify_*`,M2.53 最小版 `[meow_ui.h §9.1]`):
- 常量:`MEOW_NOTIFY_MAX_TYPES=4`/`MEOW_NOTIFY_MAX_PER_TYPE=4`/`MEOW_NOTIFY_MAX_MEDIA=1`/`MEOW_NOTIFY_TIMEOUT_ONGOING=-1`/`MEOW_NOTIFY_TIMEOUT_NEVER=0`
- 分类:`CAT_GENERAL/MESSAGE/EMAIL/EVENT/PROGRESS/MEDIA(=5)/COUNT`;紧急度 `URG_LOW/NORMAL/HIGH/CRITICAL`
- `meow_notify_register_type(cat)`/`meow_notify_send(const meow_notify*)`(返回 id)/`meow_notify_cancel(id)`/`meow_notify_active_count`/`count_in_type`/`has_active`/`urgency_str`/`category_str`
- **本阶段落点=SDK 内部活动表 + meow_log() 打日志**;真实投递通知中心 UI / D-Bus 是后续任务 `[meow_ui.h 注释]`
- `meow_config_*`(app 配置读写,走 meow_settings 后端)——**SDK 缺失清单第 3,未定** `[WORK_STATE]`
- `meow_media_*`(媒体会话)——**依赖阶段 D 落地,未定** `[WORK_STATE]`
- 崩溃捕获/看门狗——**规划中未定** `[WORK_STATE SDK 缺失清单 #5]`
- `meow_notify_dbus`(org.freedesktop.Notifications 桥)——**已定,待实现** `[FRAMEWORK_DESIGN 附录 C]`
- **meow_svcd 服务管理器**(`patch_v2/meow_svcd/`,mipsel 静态 ~99KB 进固件,不入卡)`[meow_svcd.md]`:
- 类 systemd/systemctl,由 supervisor(meow_launcherd/bootmenu)`fork/exec` 托管;**接入 supervisor 启动链为后续**,接入用 `-f` 前台便于 `waitpid`。
- 读 TF 卡 **`MeowOS/services.d/<name>.conf`**(目录式 `key=value`,未知键忽略/前向兼容):`exec`(必填)/`args`/`env`/`enabled`(0=永不自动启动,默认0)/`restart`(`always`/`on-fail`/`never`,默认on-fail)/`backoff_ms`(默认1000)/`max_restart`(默认5)/`cap`(本阶段仅解析不实装)/`trigger`(`boot`/`card-mount`/`wifi-up`,默认card-mount)。
- 崩溃隔离:服务=svcd **独立子进程**(`fork+execv`),svcd 只 `waitpid`/`SIGCHLD` 感知;服务死不影响 svcd/supervisor;重启受 `backoff_ms` 退避防热循环。
- 状态机:`DISABLED/STOPPED/RUNNING/STOPPING/FAILED`;稳定运行 30s 清零 restart_count。CLI:`status/reload/start|stop|restart <name|all>/pid`(AF_UNIX 单行文本 `/tmp/meow_svcd.sock`)。
- **卡上外部工具 = `MeowOpt/`**(TF 根下平级目录,如 `MeowOpt/mdnsd/mdnsd`):MeowOS 启动时从卡加载,拔卡降级不崩 `[DEV_NOTES][meow_svcd.md]`。
- **mDNS 方案A(已拍板)**:用**完整 `mdnsd`**(994KB, mipsel 静态) 放 TF `MeowOpt/mdnsd/mdnsd`,由 meow_svcd 托管(需 root / setcap `cap_net_bind_service,cap_net_raw`);**SAResponder**(885KB) 因"单服务注册型"(只回单服务查询,无法按名访问设备)被排除。⚠️ 手机热点组播常在客户端间丢失 → mDNS 有风险,主机 DNS 兜底 `[DEV_NOTES 检查点]`。
- `meow_settings_*`(设置后端,已定)/`meowcli`/`meow_sys_devattr`/`meow_devattr_set` `[MEOWOS_API]`
- 后台权限:`MSG_HELLO/MSG_REGISTER.flags` 扩展 `MF_BACKGROUND`/`MF_PLAYBACK`;`PERF_BACKGROUND`/`PERF_AUDIO_BACKGROUND`(规划)`[FRAMEWORK_DESIGN 附录 A]`
---
## 5. 关键约定 & 约束
### 5.1 按键/手势/状态栏/全屏
- 按键全局接管(除电源菜单),见 §2.4 `[APPS §3.4.1]`
- **左缘返回手势**:手指从**屏幕左缘 ≤24px** 向内(右)划 **≥90px**,**抬手(release 边沿)才触发** `MEOW_SWIPE_LEFT`("左滑=返回"契约);过程以 `on_swipe_progress` 实时上报 + SDK 自动画顶部进度条 `meow_ui_swipe_hint(x)`(5px 高,top,theme accent 色);x<=0 清条。**中部左/右滑不是返回**(中部右滑→SWIPE_RIGHT,中部左滑→落 TAP)`[MEOW_APP_SDK §6][GESTURE_BACK §2.2/§3]`
- 偏差:原「左缘+向左 mdx<-90」物理不可达 → 取「左缘向内(右)划 ≥90px」,事件仍报 `MEOW_SWIPE_LEFT` `[GESTURE_BACK §3]`
- **全局状态栏**:SDK 内置,默认显示(时钟/电量/WiFi/蓝牙/音量),1s 轻刷,z 最顶;仅 APP 声明全屏/`fullscreen:1` 才隐藏;非全屏 APP 须用 `meow_ui_statusbar_height()` 做 inset `[meow_ui.h §3.1][MIGRATION_AC §3]`
- 沉浸:`app.json immersive:1` → launcher 写 `/tmp/meowapp_state=1` → 隐藏虚拟返回键,手势归 SDK `[APPS §3.5][GESTURE_BACK §2.4]`
### 5.2 主题
- **日/夜/自动**:SDK `meow_theme` 内置 `meow_theme_light/dark`;模式键 `display.theme_mode`(SYSTEM_SETTINGS 记为 `manual`/`auto`——**与 SDK 枚举 light/dark/auto 冲突**,见 §A);AUTO 判时段 `[SYSTEM_SETTINGS §1][MEOW_APP_SDK §8]`
- 背景图系统:`display.bg_mode`(color/image)/`display.bg_dark_color`/`display.bg_light_color`/`display.bg_image`/`display.bg_image_dark`/`bg_image_light`/`display.bg_overlay_alpha`(0-255 默认 ~120);图片目录 **`MeowData/backgrounds/`**(480×720 约束);叠加层颜色随主题(深=黑叠/白=白叠)`[MAIN_MD3_PLAN §6][DEV_NOTES #12/#13]`
- 主界面背景:深色用 background(可选色)、浅色用 surface(白) `[DEV_NOTES #13]`
- **TF 卡多字体库(M2.5x)**:
- 目录 **`<卡根>/MeowOS/fonts/<family>/`**(每套一个子目录),内含三件套:`font.png`(预渲染灰度 PNG,bit depth 4|8)+ `font.idx`(MFNI v2 索引),二者均由 `font/gen/gen_font.py` 生成;`font.json` 为元数据+完整性校验。**缺任一件 → 该套不进列表 + 日志**。
- **font.json schema(定版)**:`family`(同目录名,信息用)/`name`(下拉显示名,缺则回退目录名)/`glyph_count`(信息用)/`size_list`(信息用)/`bit_depth`(4|8,信息用)/`sha256_png`(font.png 的 sha256 低 64hex)/`sha256_idx`(font.idx 的 sha256)/`source`(可选)/`license`(可选)。校验失败**仅 WARN 不硬失败**(该套仍可选);缺 font.json 或解析不出 `name` → 跳过。
- **加载优先级**:`font.file`(设置键,默认 `MeowOS/fonts/default/font.png`)指向的字体**存在且能 load → 用它**;否则回退卡默认 `MeowOS/fonts/default/font.png` → 固件 `/usr/share/meowos/font/font.png`。相对路径按卡根 `/usr/data/mnt/sd_0/` 解析。全失败 → 字库不可用,`ui_draw` 回退 5x7 点阵(系统不死)。
- **默认字库目录**:默认字体统一放 **`<卡根>/MeowOS/fonts/default/`**(`font.png`+`font.idx`,可选 `font.json`),不再用 `MeowAPPs/fonts/font.png`;设备旧 `MeowAPPs/fonts/` **保留**(勿删,避免破坏老约定/已有文件),仅新引用一律指向 `MeowOS/fonts/default`。
- **`font.file` 变更即 unload+reload 生效**(设置页回调);拔卡 → 回退固件内置。
- **preset 动态化**:启动/进设置页扫描一次 `MeowOS/fonts/*/`,重建「字体文件」下拉(默认字体 + ≤16 套卡内字体;上限防爆)。扫描仅此二时机,勿放热路径。
- **MeowPanel 预留**:`meow_font_import_zip()`/`meow_font_export_zip()` 为 TODO 声明(不实现),供 MeowPanel 后续接入(`.zip` 导入校验→解压到 `MeowOS/fonts/<family>/`、导出打包)。
- **多字体(M2.5x,`display.multi_font`)**:按字符类别(CJK/CJK_SYM/NUM/LATIN/LATIN_SYM/OTHER)逐字符路由,每类可各选一套字库(`font.class_*`,默认空=跟随全局 `font.file`);同 family 去重、同时装载不同字体 ≤4 套(超出 WARN「过多不同字体会增内存」并截断);开关关 = 单字体(现状)。详见 §5.7.7「多字体」。
### 5.3 通知配额/转储
- **每 App 最多 4 类型;每类型活动 ≤4;媒体单例(每 App 仅 1 条,可多 App)**;系统事件抽象为 App(`app_id=system`) 走同一配额 `[NOTIFICATION_SYSTEM §7][meow_ui.h][DEV_NOTES #11]`
- 通知创建 **10s 后自动转储到 TF `MeowOS/notifications/`**(保留最新 10MB ring,不被电源事件清);正常关机先转储再清板载;无卡可运行 `[NOTIFICATION_SYSTEM §8]`
### 5.4 配置版本单点 / 刷新率 / 息屏
- /etc/meowos_version 版本单点(见 §1.1)`[DEV_NOTES #4]`
- 刷新率:`display.refresh_rate` enum 60/30/15(默认 60);`display.refresh_always_max` bool false(关=允许 60→30→15 降档)。governor:连续 12 帧超预算降一档,连续 4 批≈48 帧远低预算升一档 `[SYSTEM_SETTINGS §1][PERF_SCHEDULER][MIGRATION_AC §12.1]`
- 息屏:`display.screen_off_timeout` int 秒 默认 **30**(0=常亮);`display.screen_off_mode` enum `panel`(面板下电+背光0+FBIOPBLANK)/`black`(背光0全黑+双击亮屏) `[SYSTEM_SETTINGS §1]`
- 亮度 clamp:`display.brightness` 0-255 默认 101(clamp ≥ `display.brightness_min`);`display.brightness_min` 默认 **1**(M2.39 由 25 改 1)——**与旧文档 25 冲突见 §A** `[SYSTEM_SETTINGS §1]`
### 5.5 MeowAPPs 包结构 / .mpk / 数据
- `<pkg>/` = 程序主体+app.json+资源;`MeowData/<pkg>/{data,cache}` = 数据;首次启动自动建 data/cache 并经 env 注入,exFAT 无软链 `[APPS 附录 §1/§2]`
- `.mpk` = tar.gz(app.json + meow 二进制 + 资源),**不含 data/cache**;导入校验 app.json/哈希→解压→数据 init→登入列表 `[APPS 附录 §3]`
- 包管理 **CLI `nyai`**(静态 MIPS,部署 `MeowOS/opt/bin/nyai`):install/remove/list/info/search/index/export/upgrade/scan;源 `MeowOS/opt/nyai/sources.list`;索引 `Packages`(Package/Version/Filename/Size/SHA256/Depends/Description)`[APPS 附录 §5]`
- 应用数上限 **8**(单屏 8 行);扫描深度 1 级;`app.json` 字段:name(仅 ASCII)/exec(静态 MIPS32r2 ELF)/version/author + **`package`(反域名权威 app_id;==目录名;缺省回退目录名)** + 扩展 `framework`/`immersive`/`icon`/`route.<id>`/`awake.<id>`(keep_awake)/`service.<svc>`/`fullscreen`(**未解析**,见矛盾 §A-12) `[APPS §2][MEOW_APP_SDK §9][FRAMEWORK_DESIGN §2][源:审计 2026-08-30]`
### 5.6 冷启动充电屏
- 触发(**三者同时**):冷启动(`poweroff` 写 `/data/meow_cold_boot=1`;`reboot` 写 0)+ 在充电(AC online=1 或 battery status=Charging)+(开机瞬间一次性快照,判定后不回头)`[CHARGING_SCREEN §0]`
- 热启动(reboot、含充电态 reboot)一律**不进**充电屏,走引导选单 `[CHARGING_SCREEN §0]`
- 主题:`theme.charging=<id>`(默认 default);`MeowOS/themes/charging/<id>/theme.json`;加载失败回退内置纯代码默认主题 `[CHARGING_SCREEN §1/§2]`
### 5.7 字体管理 + 应用字库接口(扩展 → SDK 统一接口 / 应用自带字库 / 多句柄)
> 在 §5.2「TF 卡多字体库(M2.5x)」基础上**扩展**:把 MeowOS 字体管理器定义为可用字库的**唯一权威来源**,向 SDK 提供统一查询/选用接口,并支持**应用自带字库**与**多句柄(多字体)**。
> ⚠️ **凡 `meow_font_*_h` / `meow_ui_*_h` / 列表枚举 / 句柄加载类接口均为「草案/待定案」**:当前 SDK 只有单字体 `meow_font_*` 与 `meow_ui_text*`(用当前默认字体),本小节为新功能、**未实现**,勿当作已落地。
> `[源:meow_font.h][源:agent-79 实现][源:meow_ui.h]`
> **app 未自带字库 → 跟随系统 `font.file`(M2.x 已落地)**:launcher 每次 `launch_app` 前把「当前生效字体」注入为环境变量 `MEOW_FONT_PNG`/`MEOW_FONT_IDX`(绝对路径,可选 `MEOW_FONT_APP=<family>`);SDK `meow_ui_gfx.c load_font()` **优先读 env**,无 env 则回退卡默认 `MeowOS/fonts/default` → 固件。§5.7.3 的 `load_handle`(app 自带字库)**未实现**,故当前 app 只能跟随系统字体;一旦实现自带字库,其加载优先级应高于 env。
- **5.7.1 字体管理器(launcher 侧)= 可用字库唯一权威来源**
- 唯一维护并扫描 `MeowOS/fonts/<family>/`(+默认),产出「字体列表」(family slug / 显示名 / glyph_count / size_list / bit_depth)。**SDK 不自行发现字库**,一律经本接口取 launcher 扫描结果。
- 扫描与校验规则沿用 §5.2:三件套 `font.png/font.idx/font.json` **缺任一件 → 该套跳过 + 日志**;`font.json` 解析 `name`(缺回退目录名)/`glyph_count`/`size_list`/`bit_depth`;`sha256_png/sha256_idx` 仅 **WARN** 不硬失败(该套仍可选)。
- 列表上限沿用 `FONT_PRESETS_MAX = 17`(1 默认 + ≤16 卡内套装,防爆);顺序 = 默认(0) + 扫描顺序。扫描时机不变(启动 / 进设置页),**勿放热路径** `[源:agent-79 实现]`。
- 权威列表数据模型(SDK 侧快照,枚举时填充):
```c
typedef struct meow_font_info {
char family[64]; /* family slug = MeowOS/fonts/<family>/ 目录名 */
char name[64]; /* font.json "name",缺则回退 family */
int glyph_count; /* font.json "glyph_count",信息用 */
int size_list[16]; /* font.json "size_list"(原生面字号,0 结束) */
int size_count; /* 有效字号数 */
int bit_depth; /* 4 | 8 */
char path_png[320]; /* 系统库:相对卡根 MeowOS/fonts/<family>/font.png */
} meow_font_info;
```
- **5.7.2 应用可读 TF 卡字体列表(统一规范接口,app 面向)** `[源:agent-79 实现][源:meow_font.h]`
```c
int meow_font_get_available_count(void); /* 可用字库数(含默认) */
int meow_font_enumerate(int idx, meow_font_info *out); /* 按序号取,越界返回 0 */
typedef int (*meow_font_enum_cb)(const meow_font_info *info, void *ctx);
int meow_font_enumerate_cb(meow_font_enum_cb cb, void *ctx); /* 回调式,返回套数 */
int meow_font_select_by_id(int id); /* 选该套为 app 会话默认字体 */
```
- 语义:`id` = 列表序号(§5.7.1 快照);`0` = **跟随系统默认**(用户 `font.file` 所选,app 会话不覆盖);`>0` = **app 会话内固定用该套**(覆盖 `font.file` 至 app 结束)。成功 0,越界/加载失败返回负值。
- **列表快照是临时的**:launcher 仅启动/进设置页重扫,期间拔卡或改卡内字库不刷新;app 应**每次会话重新枚举**、按 `family` 持久化,勿缓存数值 id。
- 覆盖范围:系统库 `MeowOS/fonts/<family>/` 与默认(含固件 `/usr/share/meowos/font` 回退)都反映在列表里;app 侧「选用已有字库」**只用本接口,不直接拼路径**。
- **5.7.3 应用自带字库(按 handle 加载)** `[源:meow_font.h]`
- 目录:`MeowAPPs/<pkg>/fonts/<handle>/{font.png,font.idx,font.json}`;`<pkg>` = `app.json.package`(反域名 app_id,见 §5.5),`<handle>` = 应用自设名字(如 `lyrics`/`reader`)。
- `app.json` 声明(**可选**):`"fonts": ["lyrics","reader"]`。作用 = MeowPanel 打包校验 / launcher 装包校验 / SDK 提供取证;**不声明也可运行时按 handle 加载**。
- SDK 接口(草案):
```c
int meow_font_load_handle(const char *pkg, const char *handle); /* 返回字体句柄(>0),失败负值;pkg=NULL=当前 app */
void meow_font_unload_handle(int h);
int meow_font_handle_info(int h, meow_font_info *out); /* 查句柄对应信息 */
```
- **应用自带字库校验更严**:三件套缺任一或 `font.json` 解析不出 → 加载**失败**(app 自声明字库,坏库应显式失败,而非静默回退点阵/默认)。
- 与系统库**并存可混用**:系统套件经 §5.7.2 `meow_font_select_by_id` 激活即成合法 handle;应用自带经 `load_handle` 取得 handle;两者在同一 handle 空间。
- **5.7.4 多句柄 / 多字体(不同控件用不同字体)** `[源:meow_font.h][源:meow_ui.h]`
- 低层 `meow_font_*` 新增 `_h` 句柄版本(显式传 handle):
```c
void meow_font_drawtext_h(uint16_t *fb,int x,int y,const char *utf8,uint16_t color,int size,int handle);
void meow_font_drawtext_outline_h(uint16_t *fb,int x,int y,const char *utf8,
uint16_t color,uint16_t outline_color,int ol,int size,int handle);
int meow_font_width_text_h(const char *utf8,int size,int handle);
int meow_font_line_height_h(int size,int handle);
int meow_font_ascent_h(int size,int handle);
int meow_font_has_size_h(int size,int handle);
```
- **兼容关键**:现有无 `_h` 的 `meow_font_*`(drawtext/width_text/line_height/...)语义变更为「作用于**当前句柄**」(默认 = 系统 `font.file` 那套);`meow_font_load(png,idx)` 仍是装载系统默认的入口;新增 `meow_font_use(handle)` 设定当前句柄。**不改任何现有签名 → 纯扩展、向后兼容。**
```c
void meow_font_use(int handle); /* 设定后续无 _h meow_font_* 所用字体 */
int meow_font_get_current(void);
```
- SDK `meow_ui_*` 高层文本同理:
```c
void meow_ui_use_font(int handle); /* 设定后续 meow_ui_text* 字体 */
int meow_ui_font_get_current(void); /* 取当前 meow_ui_text* 所用句柄 */
void meow_ui_text_h(int x,int y,const char *utf8,int size,uint32_t color,int handle);
void meow_ui_text_right_h(int right_x,int y,const char *utf8,int size,uint32_t color,int handle);
void meow_ui_text_center_h(int cx,int y,const char *utf8,int size,uint32_t color,int handle);
int meow_ui_text_width_h(const char *utf8,int size,int handle);
int meow_ui_text_height_h(int size,int handle); /* = meow_font_line_height_h */
```
现有 `meow_ui_text/text_right/text_center`(无 handle)= 用当前字体(`meow_ui_use_font` 设;默认系统默认)。**向后兼容。** 建议 app 切库前用 `meow_font_get_current()` / `meow_ui_font_get_current()` 求值保存,画完再 `meow_ui_use_font(旧)` 显式恢复,避免句柄状态泄漏影响后续绘制。
- **5.7.5 多句柄用法示例(歌词页用 A 库、正文用 B 库)**
```c
/* 应用自带 lyrics(歌词页) + 系统字库(正文)混用 */
int hLyrics = meow_font_load_handle(NULL, "lyrics"); /* MeowAPPs/<pkg>/fonts/lyrics/ */
meow_ui_use_font(hLyrics);
meow_ui_text_center(240, 300, "歌词行…", 20, 0xFFFFFF); /* 用 lyrics 库 */
int hBody = meow_font_select_by_id(2); /* 系统字库第 2 套(正文用) */
meow_ui_use_font(hBody);
meow_ui_text(20, 60, "正文…", 20, 0xFFFFFF); /* 用系统库 */
/* 量宽/行高须与最终实际字形一致:用同 handle 的 _h 版 */
int w = meow_ui_text_width_h("正文…", 20, hBody);
int lh = meow_ui_text_height_h(20, hBody);
```
- 说明:句柄状态为 app 进程内**全局**;同一屏需混排时,推荐每段绘制前显式 `meow_ui_use_font`,或全部走 `*_h` 显式传 handle,避免依赖上次绘制遗留的句柄状态。
- **5.7.6 MeowPanel 上传 / 导出(.zip,预留)** `[源:meow_font.h]`
- 复用已声明的 `meow_font_import_zip(zip_path)` / `meow_font_export_zip(family,out_zip)`(§5.2 已列为 TODO,未实现)。
- **系统字库导入**:`.zip` 内含 `font.png+font.idx+font.json` 三件套;校验三件套就绪 + `font.json` 可解析;sha256 沿用 `font.json` 约定(建议与运行时同口径 = **WARN**,仅缺件/不可解析硬失败);`family` 取自 `font.json.family` 或 zip 名;解压到 `MeowOS/fonts/<family>/`;**覆盖冲突需先确认**;导入后应触发 launcher 重扫(刷新 §5.7.1 列表)。
- **应用字库导入**:目标 `MeowAPPs/<pkg>/fonts/<handle>/`,与 `app.json "fonts"` 声明对齐,校验同上。
- **导出**:系统库把 `MeowOS/fonts/<family>/` 三件套打包;应用库把 `MeowAPPs/<pkg>/fonts/<handle>/` 打包。
- 约定:`.zip` 布局与校验沿用 `font.json` schema(§5.2);导入/导出后的一致性(列表刷新、应用声明同步)归 MeowPanel + launcher 协作,本小节仅列接口语义。
- **5.7.7 多字体(按字符类别逐字符路由,`display.multi_font`,M2.5x 新增)** `[源:meow_font.h][源:MEOWOS_SPEC_REF §5.2/§5.5]`
- **背景**:一款字体难兼顾中文(大图集、字形全)与拉丁/数字(干净、省内存)。多字体让**不同字符类别各用一套字库**,按 codepoint 逐字符路由取字形。
- **设置键**(launcher 读,SDK 经 env 读同一映射):
- `display.multi_font`(int **0/1,默认 0=单字体**):1=按字符类别逐字符路由;0=只走 `font.file`(现状,零额外内存/性能开销)。
- 6 个类别字体(SET_STR,值 = 字体 family 相对路径,**默认空 = 跟随全局 `font.file`**):`font.class_cjk`(CJK 表意+扩展)、`font.class_cjk_sym`(全角/中文标点)、`font.class_num`(0-9)、`font.class_latin`(A-Za-z)、`font.class_latin_sym`(半角标点)、`font.class_other`(其他)。
- **字符分类器**(`meow_font_class_of(cp)`,按 codepoint):`MEOW_FCLS_CJK`/`_CJK_SYM`/`_NUM`/`_LATIN`/`_LATIN_SYM`/`_OTHER`。规则(ASCII 优先 + Unicode 区间):0x30-39→NUM、0x41-5A/61-7A→LATIN、<0x80(其余)→LATIN_SYM;0x3000-303F/0xFF00-FFEF/0x2014/0x2018-201D/0x2026/0x00B7→CJK_SYM;CJK 表意+扩展+兼容表意区(0x3400-4DBF/4E00-9FFF/20000-2FA1F…)→CJK;其余(假名/韩文/其他文字/扩展区)→OTHER。
- **逐字符路由**:`meow_font_drawtext`/`_outline`/`width_text`/`line_height`/`ascent`/`has_size` 在 multi_font 开启时**逐字符分类 → 用类别对应槽的字库取字形与度量**(宽度/行高按该字体);缺某类字体/槽未载 → **回退全局**(slot0);该字符其字体无字形 → **豆腐缺字**(可经 `meow_font_has_glyph(cp)` 预判)。开关关 → 一律 slot0,与单字体一致。
- **SDK 接口**:`meow_font_load_slot(slot,png,idx)`/`meow_font_unload_slot(slot)`/`meow_font_enable_multifont(on)`/`meow_font_set_class_slot(cls,slot)`/`meow_font_config_multifont(on,global_png,global_idx,cfg[],&distinct,&truncated)`;`MEOW_MAX_SLOTS=5`(slot0=全局 + ≤4 类别)。`meow_font_config_multifont` 统一做**同 png 去重**(含与全局相同 → follow slot0)与**≤4 套上限**(超出 → 置 `*truncated=1`,调用方 WARN「过多不同字体会增内存」,已装载者保留、新类别回退全局)。
- **launcher env 注入**(launch_app,app 跟随系统字体):`MEOW_MULTI_FONT=0/1`;`MEOW_FONT_PNG/IDX`(全局,保留);6 类 `MEOW_FONT_CLS_<类>_PNG/IDX`(命中则覆盖全局;类值为空=跟随全局不注入)。SDK `meow_ui_gfx` 读 env 构建同一映射;无 env/关 → 单字体。
- **持久化**:类别字体设置在 settings.conf(板载,无卡也可存),经 `meow_settings_*` 读写,随设置页变更即重配。
- **内存**(推断解码 atlas = `plane_w×plane_h×(depth 4→0.5 / 8→1.0)` 字节;每套另加 glyph 数组 ≈ glyph_count×16B、idx 头保留约 128KB,idx 原始缓冲载毕即释)。实测仓库字库(depth 4):misans(CJK)≈2.44MiB、source_han_sans(CJK)≈2.53MiB、meslo(Latin)≈1.68MiB、google_sans(Latin)≈1.12MiB;按用户估算口径(**depth 8**):CJK ≈ 5-6MB、Latin ≈ 0.3-0.5MB(后者为窄覆盖 Latin 专库)。**典型「1CJK+1Latin」增量**:全局=CJK,另加一套 Latin → 增加 ≈0.3-1.7MB(depth 8 约 0.5MB;实测 depth4 latin 1.1-1.7MB);全局=Latin 另加一套 CJK → 增加 ≈2.4-2.5MB(depth 8 约 5-6MB)。`display.multi_font=0` 时仅全局一套,无任何额外装载。
---
## 6. 标志性 TODO / 未决(文档未定,勿凭猜实现)
- OPEN_QUESTIONS.md 待定 ❓:#1 背景图加载时机/缓存、#2 非 480×720 图如何处(拉伸/裁剪/回退)、#3 叠加层颜色联动、#4 背景色板具体枚举、#5 浅色主题文字对比度、#7 首期是否做应用图标、#8 通知来源(**最大空白**,M2 已定为 系统+IPC+D-Bus 三路)、#9 下拉手势 vs 左滑返回区分、#10 通知存储上限/FIFO、#11 媒体活跃会话判定、#12 多 app 音频混音/焦点、#13 web 实时画面 JPEG/WS、#14 远程输入注入仲裁、#16 主页左滑=侧边栏 vs 返回 `[OPEN_QUESTIONS]`
- DEVELOPMENT_PLAN:阶段 0(bootmenu 双系统)**待实现**(M0-M4);阶段 B/E/F;M2-M6 阶段 D 里程碑未做 `[DEVELOPMENT_PLAN]`
- 未定/待拍板:`meow_config_*`/`meow_media_*`/崩溃捕获(见 §4);MeowOS 音频输出设置(只读还是可配);OTA 依赖 MeowPanel `[WORK_STATE][OPEN_QUESTIONS #17/#18]`
- **meow_svcd 待办**:接入 supervisor 启动链(`-f` 前台 + waitpid,改固件有风险需另确认);`cap` setcap 真机实装(cap_net_bind_service,cap_net_raw);写 `MeowOS/services.d/mdnsd.conf` 落地 mDNS。**services.d/svcd 尚未接入 supervisor,勿当作已跑起来。** `[WORK_STATE][meow_svcd.md]`
---
## 7. 已知矛盾 / 待确认(⚠️ 别凭猜)
- **A-1 热键窗口下限**:APPS.md §3.1/§4.2 写「电源按下后 **300ms**~2.5s」;DEVELOPMENT_PLAN §0/阶段A 写「窗口下限 **60ms**(v6.7 修)。→ 以 **60ms** 为准,APPS.md 已过时。
- **A-2 主题模式枚举**:SYSTEM_SETTINGS §1 `display.theme_mode`=`manual`/`auto`(另设 `display.theme`=dark/light);MEOW_APP_SDK §8 / meow_ui.h `meow_theme_mode`=`LIGHT/DARK/AUTO` 且直接跟随 `display.theme_mode`。→ 两套枚举语义不一致;AUTO 时段:SYSTEM_SETTINGS 用可配 `theme_dark_start/end`(分钟),SDK §12 用固定「6:00-18:00 日间」。WORK_STATE/DEV_NOTES 明言「时段判定 launcher/SDK 两份逻辑需抽共享纯函数」。→ **DOM 键值 enum 与 SDK enum 需统一,时段判定需抽共享函数后再实现。**
- **A-3 亮度下限**:`display.brightness_min` 默认 **1**(SYSTEM_SETTINGS §1,M2.39 由 25 改 1);但 MEOWOS_API §2.2「clamp ≥ brightness_min 默认 **25**」、MD3_UI_SPEC §3.2「亮度 clamp ≥25」仍写 25。→ 以 **SYSTEM_SETTINGS(1)** 为准,另两份文档陈旧。
- **A-4 左缘返回阈值**:MEOW_APP_SDK §6 / GESTURE_BACK 取「左缘 ≤24px + 向内划 **≥90px**,抬手触发」;MIGRATION_AC §7 写「左缘 24px + 右滑 **≥65px** 触发」。→ **90 vs 65 不一致**(meow_ui.h 未给阈值,GESTURE_BACK + MEOW_APP_SDK 较权威=90,但确认真机前留疑)。
- **A-5 通知 app_quota**:NOTIFICATION_SYSTEM §7/meow_ui.h = 4 类型×每类型 4=16 条/App;SYSTEM_SETTINGS §1 `notify.app_quota`=16。FRAMEWORK_DESIGN §4「配额 ≤16/应用」。→ **口径可归并(4×4=16)**,但 SYSTEM_SETTINGS 未列 4/4 细分,建议实现以 meow_ui.h 的 `MEOW_NOTIFY_MAX_TYPES/MAX_PER_TYPE` 为准。
- **A-6 KEY_PREVIOUS(code)**:KEY_CONTROL §3 明注「KEY_PREVIOUSSONG 是 **165**;19 是另一码」;meow_ui.h `#define MEOW_KEY_PREVIOUS 19 /* KEY_PREVIOUSSONG */` 注释标错。→ **19 的标签应改**(值 19 非 prevsong;165 才是),属 meow_ui.h 注释误导。
- **A-7 app 日志路径**:APP_LOG_MANAGER §4 写 `apps/<app_id>.log`(单文件);meow_ui.h §9 / DEV_NOTES #9 为 **`apps/<包名>/logs/<启动时间>_<pid>.log`**(每次启动新文件)——用户已纠正,勿用单文件。→ 以 meow_ui.h/DEV_NOTES(M2.51)为准,APP_LOG_MANAGER 目录小节过时。
- **A-8 状态栏高**:MEOW_APP_SDK §3.1「slim ~20-40px」;实际定案 **40px**([D6] MIGRATION_AC §11.1),后被用户改为 **28px**(MUI_SBAR_H=28,字号 20,图标 ink 16/中线 14,见 M2.x 状态栏压缩)。→ 现取 28。
- **A-9 SDK 通知转储**:NOTIFICATION_SYSTEM §8「创建 10s 后自动转储到 TF」;meow_ui.h 现仅「活动表+meow_log 打日志,真实投递 UI/D-Bus 为后续」。→ 10s 转储/TF 尚未实现,属"已定未做"。
- **A-10 版本来源细解**:DEV_NOTES #4「/etc/meowos_version 唯一来源;MEOWOS_VERSION 宏仅 dev 占位永不动」;APPS.md §4.6「MEOWOS_VERSION 宏=单一来源,build 时 sed 写入 etc/meowos_version」。→ 两者都强调"写入同源",但"谁是源头"措辞矛盾;实践上 build 脚本 echo 生成 /etc/meowos_version,宏作屏显 dev 占位。
- **A-11 `MeowOS/opt/` vs `MeowOpt/`**:§1.2 树中 `MeowOS/opt/{bin,nyai,sources.list},lib/,tools/`(nyai 包管 + 工具)与新增顶层 `MeowOpt/`(板载外部工具/二进制,如 mdnsd)并存,命名仅大小写之差、语义可能重叠。→ **两者是否为同一用途/是否需归并待确认**;当前按各自文档记录,勿混用。
- **A-12 `fullscreen` 字段未解析**:§5.5 与 MEOW_APP_SDK §9 将 `fullscreen` 列为 app.json 字段,但 `meow_parse_app_json()` **并未读取该键**(实现只解析 name/exec/icon/package/framework/immersive/route./awake./service.)。→ 文档与实现不一致,属"已定未做";若要用需在解析器补读并处理。
`[各源标注见上]`