SDK: 同步主仓 M15/M16/bug3/MD3 修复 — 时钟 ABI 补全/IME 冷却窗/列表行高派生/形状 token/翻页键
公开 SDK 落后主仓的一批 bugfix(主仓是固件构建源,这些修复已在设备上跑过)。 本次只做「主仓 → 公开仓」单向同步,图像栈方向由主仓侧另一单处理。 时钟 ABI(M16 第二弹,原文件自认「残余未修」): - meow_ui_time.c 147→345 行:futex 相对超时接管(__timedwait/_cp)、 timerfd_create/settime/gettime 的 itimerspec 64↔32 双向转换、 __clock_settime64 越界返 ENOTSUP,另有 4 个纯换算函数 - meow_ui_internal.h:struct meow_time32 / meow_itimerspec32 契约移入内部头 - CLOCK_ABI.md:补接管机制、验证配方与 objdump 证据 - 新增 test_meow_time64.c IME bug3(成对才有意义): - meow_ui_ime.c:IME_TAP_COOLDOWN_MS 200 冷却窗 + 打开时二次 drain - meow_ui_input.c:meow_input_touch_reset() 并在 drain 内调用(复位触摸状态机) - test_ime_fix.c:新增用例④ stray-tap 列表行高(M15,修用户可见 bug): - meow_ui_widget.c:listv_item_h() 由主题字体行高派生,不再写死 56 (两行列表 62 > 56 会让首行标题被裁剪守卫整条跳过) - include/meow_ui_widgets.h:新增 meow_listview_item_h() - 新增 test_meow_ui_listview_rowh.c 其余:meow_select.c / meow_ui_dialog.c 统一 MD3 形状 token; include/meow_ipc.h 补 MSG_KEY_PAGEUP/PAGEDOWN 枚举; meow_ui_sys.c / meow_cachegov.c 取时统一走 meow_ui_time_ms()。 测试辅助函数标定:tuku/test/test_settings_lock_host.c 的注入前等待 150ms→350ms。 该等待按修复前 IME 标定,新冷却窗下首键 dt_open≈114ms 会被当迟到抬起吞掉, 只录到 "68" 两位。仅改等待时长,断言原样保留。 验证:tuku 四套脚本全绿(run_tests 644 PASS / zip 106 / cbz 296 / webtoon PASS); 12 个源文件与主仓逐字节一致;sdk/build_sdk.sh 34 成员; tuku/build_tuku.sh 产出静态 MIPS32r2 ELF。
This commit is contained in:
1 parent
38cc9d4acb
commit
27a3750e36
37 files changed
+1026
-111
No files matched your search
@@ -0,0 +1,170 @@
|
||||
/* test_meow_time64.c — 宿主单测:time64 → 内核 o32 time32 的换算与结构宽度。
|
||||
*
|
||||
* 背景(M16):zig clang 给 32 位 mips 预定义 __ILP32__,打穿 musl 的 time64 回退守卫,
|
||||
* futex 相对超时 / timerfd / clock_settime 等入口把 16 字节(time64)结构直接交给 time32
|
||||
* 系统调用。meow_ui_time.c 的接管入口统一经 meow_ui_internal.h 里这几个纯换算函数转换,
|
||||
* 本测试在宿主上把「换算结果 + 内核实际读到的宽度」固定住,不需要 mips 设备。
|
||||
*
|
||||
* 编译(patch_v2/sdk 目录下):
|
||||
* gcc -Os -Wall -Wextra -I. -Iinclude -c meow_ui_time.c -o /tmp/meow_ui_time.o
|
||||
* gcc -Os -Wall -Wextra -I. -Iinclude test_meow_time64.c /tmp/meow_ui_time.o \
|
||||
* -o test_meow_time64
|
||||
* 运行:./test_meow_time64 (exit 0=PASS / 1=FAIL)
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "meow_ui.h"
|
||||
#include "meow_ui_internal.h"
|
||||
|
||||
static int g_fail = 0;
|
||||
|
||||
static void check(const char *name, int ok)
|
||||
{
|
||||
if (ok) {
|
||||
printf("ok %s\n", name);
|
||||
} else {
|
||||
printf("FAIL %s\n", name);
|
||||
g_fail = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_time32(const char *name, const struct meow_time32 *got,
|
||||
int32_t sec, int32_t nsec)
|
||||
{
|
||||
if (got->tv_sec == sec && got->tv_nsec == nsec) {
|
||||
printf("ok %s = {%d, %d}\n", name, (int)got->tv_sec, (int)got->tv_nsec);
|
||||
} else {
|
||||
printf("FAIL %s = {%d, %d},期望 {%d, %d}\n", name,
|
||||
(int)got->tv_sec, (int)got->tv_nsec, (int)sec, (int)nsec);
|
||||
g_fail = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 模拟 o32 内核对「调用者给的指针」的实际读法:只读前 8 字节,按两个 int32 解释。 */
|
||||
static void kernel_time32_view(const void *ptr, struct meow_time32 *out)
|
||||
{
|
||||
memcpy(out, ptr, sizeof *out);
|
||||
}
|
||||
|
||||
static void test_rel(void)
|
||||
{
|
||||
struct meow_time32 t;
|
||||
|
||||
meow_time32_rel_from_parts(5, 123456789, &t);
|
||||
check_time32("rel 普通值", &t, 5, 123456789);
|
||||
|
||||
meow_time32_rel_from_parts(0, 500000000, &t);
|
||||
check_time32("rel 亚秒(原缺陷会变 {0,0})", &t, 0, 500000000);
|
||||
|
||||
meow_time32_rel_from_parts(INT32_MAX, 999999999, &t);
|
||||
check_time32("rel int32 上界", &t, INT32_MAX, 999999999);
|
||||
|
||||
meow_time32_rel_from_parts((int64_t)INT32_MAX + 1, 1, &t);
|
||||
check_time32("rel 上溢饱和到 INT32_MAX", &t, INT32_MAX, 1);
|
||||
|
||||
meow_time32_rel_from_parts(INT64_MAX, 0, &t);
|
||||
check_time32("rel INT64_MAX 饱和", &t, INT32_MAX, 0);
|
||||
|
||||
meow_time32_rel_from_parts(-1, 500000000, &t);
|
||||
check_time32("rel 负值透传(调用方另判 ETIMEDOUT)", &t, -1, 500000000);
|
||||
|
||||
meow_time32_rel_from_parts((int64_t)INT32_MIN - 1, 0, &t);
|
||||
check_time32("rel 下溢饱和到 INT32_MIN", &t, INT32_MIN, 0);
|
||||
}
|
||||
|
||||
static void test_abs(void)
|
||||
{
|
||||
struct meow_time32 t;
|
||||
|
||||
t.tv_sec = 7;
|
||||
t.tv_nsec = 7;
|
||||
check("abs 普通值", meow_time32_abs_from_parts(1700000000, 250000000, &t) == 0);
|
||||
check_time32("abs 普通值内容", &t, 1700000000, 250000000);
|
||||
|
||||
check("abs int32 上界接受", meow_time32_abs_from_parts(INT32_MAX, 0, &t) == 0);
|
||||
check("abs int32+1 拒绝", meow_time32_abs_from_parts((int64_t)INT32_MAX + 1, 0, &t) == -1);
|
||||
check("abs int32 下界接受", meow_time32_abs_from_parts(INT32_MIN, 0, &t) == 0);
|
||||
check("abs int32-1 拒绝", meow_time32_abs_from_parts((int64_t)INT32_MIN - 1, 0, &t) == -1);
|
||||
check("abs 2038 后一秒拒绝", meow_time32_abs_from_parts(2147483648LL, 0, &t) == -1);
|
||||
}
|
||||
|
||||
static void test_itimerspec(void)
|
||||
{
|
||||
struct meow_time64_itimerspec in;
|
||||
struct meow_itimerspec32 out, back32;
|
||||
struct meow_time64_itimerspec back;
|
||||
|
||||
in.it_interval.tv_sec = 1;
|
||||
in.it_interval.tv_nsec = 250000000;
|
||||
in.it_value.tv_sec = 3600;
|
||||
in.it_value.tv_nsec = 999999999;
|
||||
memset(&out, 0xAA, sizeof out);
|
||||
check("itimerspec 四字段转换成功",
|
||||
meow_time32_itimerspec_from_64(&in, &out) == 0);
|
||||
check_time32("itimerspec interval", &out.it_interval, 1, 250000000);
|
||||
check_time32("itimerspec value", &out.it_value, 3600, 999999999);
|
||||
|
||||
/* 越界必须整体失败且不改 *out(timerfd_settime 回 ENOTSUP 的前提) */
|
||||
memcpy(&back32, &out, sizeof back32);
|
||||
in.it_value.tv_sec = (int64_t)INT32_MAX + 1;
|
||||
check("itimerspec 越界拒绝", meow_time32_itimerspec_from_64(&in, &out) == -1);
|
||||
check("itimerspec 越界不写坏输出", memcmp(&back32, &out, sizeof out) == 0);
|
||||
|
||||
/* 反向(timerfd_gettime)字段不串位 */
|
||||
memset(&back, 0, sizeof back);
|
||||
meow_time64_itimerspec_from_32(&back32, &back);
|
||||
check("itimerspec 反向 sec/nsec 不串位",
|
||||
back.it_interval.tv_sec == 1 && back.it_interval.tv_nsec == 250000000 &&
|
||||
back.it_value.tv_sec == 3600 && back.it_value.tv_nsec == 999999999);
|
||||
}
|
||||
|
||||
/* 结构宽度证明:同一块内存按「libc 头 ABI」与「内核 o32 ABI」读出的值不同。 */
|
||||
static void test_struct_width(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
if (sizeof(time_t) != 8 || offsetof(struct timespec, tv_nsec) != 8) {
|
||||
printf("skip 结构宽度模拟(宿主 time_t/timespec 布局与 ILP32+time64 不一致)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* 剩 0.4s:16 字节 time64 结构的前 8 字节被内核读成 {sec=0, nsec=0} → 立即超时 */
|
||||
memset(&ts, 0, sizeof ts);
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 400000000;
|
||||
struct meow_time32 old_view;
|
||||
kernel_time32_view(&ts, &old_view);
|
||||
check("旧 ABI:0.4s 被内核读成 {0,0}(立即超时)",
|
||||
old_view.tv_sec == 0 && old_view.tv_nsec == 0);
|
||||
|
||||
/* 剩 2.3s:旧 ABI 丢掉 0.3s,只剩 2s 整 */
|
||||
memset(&ts, 0, sizeof ts);
|
||||
ts.tv_sec = 2;
|
||||
ts.tv_nsec = 300000000;
|
||||
kernel_time32_view(&ts, &old_view);
|
||||
check("旧 ABI:2.3s 被内核读成 2s 整",
|
||||
old_view.tv_sec == 2 && old_view.tv_nsec == 0);
|
||||
|
||||
/* 新路径:先转换再交给内核,宽度与值都对 */
|
||||
struct meow_time32 fixed;
|
||||
meow_time32_rel_from_parts((int64_t)ts.tv_sec, (int64_t)ts.tv_nsec, &fixed);
|
||||
struct meow_time32 new_view;
|
||||
kernel_time32_view(&fixed, &new_view);
|
||||
check("新 ABI:内核读到 {2, 300000000}", new_view.tv_sec == 2 &&
|
||||
new_view.tv_nsec == 300000000);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_rel();
|
||||
test_abs();
|
||||
test_itimerspec();
|
||||
test_struct_width();
|
||||
|
||||
printf(g_fail ? "== FAIL ==\n" : "== PASS ==\n");
|
||||
return g_fail;
|
||||
}
|
||||
Reference in new issue
Block a user