Fix Android directory CRC login crash and record Mi 8 Lite device tests

This commit is contained in:
shen
2026-09-30 17:54:11 -07:00
parent 059ceadec2
commit d45c5c6cf5
5 changed files with 60 additions and 4 deletions
+1
View File
@@ -647,3 +647,4 @@
{"date": "2026-09-30", "unit": "EterLib/GrpFontTexture.cpp", "action": "improve-platform-rendering", "evidence": "Retina UI clarity: dynamic font atlas rebuild preserving cached pointers and logical metrics, 8-bit HiDPI glyph alpha, physical pixel alignment and 1:1 sampling; 2406 bundled HD textures. Full native suite 29 passed, 2 skipped, macOS packaged inventory screenshots and strict signature verification. See audit/evidence/2026-09-30-mac-ui-clarity.md."}
{"date": "2026-09-30", "unit": "EterLib/GrpImageInstance.cpp", "action": "improve-platform-rendering", "evidence": "Retina UI clarity: dynamic font atlas rebuild preserving cached pointers and logical metrics, 8-bit HiDPI glyph alpha, physical pixel alignment and 1:1 sampling; 2406 bundled HD textures. Full native suite 29 passed, 2 skipped, macOS packaged inventory screenshots and strict signature verification. See audit/evidence/2026-09-30-mac-ui-clarity.md."}
{"date": "2026-09-30", "unit": "UserInterface/PythonPlayerAutoHunt.cpp", "action": "user-authorized-extension", "evidence": "Replace tag-and-chase gather with free server-authoritative cloak-style BeginFight pull, nearest 3/10/20 actual monster groups. Server rate limit and safety checks, request generations, stationary approach wait. host.autohunt_pull and desktop/mobile port.login_flow pass; 203 FreeBSD compile/deploy and live 3-group/9-monster reply verified. See tools/server/autohunt-pull/README.md."}
{"date": "2026-09-30", "unit": "EterBase/CRC32.cpp", "action": "fix-platform-adapter", "evidence": "MI 8 Lite Android 15 fake-login SIGABRT/std::bad_alloc from directory CRC. Reject non-regular/null FILE handles and failed seeks; preserve normal CRC/position. port_utils_test pass, port_map check 0 errors; rebuilt APK installed and on-device fake-login/map entry succeeds. docs/XIAOMI8LITE-DEVICE-TEST-20260930.md"}
+2 -2
View File
@@ -30,7 +30,7 @@
"test": [
"tests/port/port_utils_test.cpp"
],
"note": "40250 maps the file (CreateFile + CreateFileMapping/MapViewOfFile from offset 0) and CRCs the whole view; the port reads the whole FILE* into a buffer. Invariant: same CRC of the full file, the handle's position is unchanged, 0 when the file cannot be opened."
"note": "40250 maps the file (CreateFile + CreateFileMapping/MapViewOfFile from offset 0) and CRCs the whole view; the port reads the whole FILE* into a buffer. Invariant: same CRC of the full file, the handle's position is unchanged, 0 when the file cannot be opened. Android 15 MI 8 Lite regression: reject non-regular FILE handles before seeking/allocating, preserving Win32 directory-open failure; check seek errors. Directory/null regression in port_utils_test and successful on-device fake-login/map entry after prior std::bad_alloc abort."
},
"GetFileCRC32": {
"status": "ADAPTED",
@@ -40,7 +40,7 @@
"test": [
"tests/port/port_utils_test.cpp"
],
"note": "40250 maps the file (CreateFile + CreateFileMapping/MapViewOfFile from offset 0) and CRCs the whole view; the port reads the whole FILE* into a buffer. Invariant: same CRC of the full file, the handle's position is unchanged, 0 when the file cannot be opened. Callers: GuildMarkUploader/GuildMarkDownloader symbol CRC, root pack CRC report."
"note": "40250 maps the file (CreateFile + CreateFileMapping/MapViewOfFile from offset 0) and CRCs the whole view; the port reads the whole FILE* into a buffer. Invariant: same CRC of the full file, the handle's position is unchanged, 0 when the file cannot be opened. Callers: GuildMarkUploader/GuildMarkDownloader symbol CRC, root pack CRC report. Android 15 MI 8 Lite regression: reject non-regular FILE handles before seeking/allocating, preserving Win32 directory-open failure; check seek errors. Directory/null regression in port_utils_test and successful on-device fake-login/map entry after prior std::bad_alloc abort."
},
"GetFileSize": {
"status": "ADAPTED",
+37
View File
@@ -0,0 +1,37 @@
# 小米 8 Lite 真机测试(2026-09-30)
已安装 Release 原生库的 debug 签名 APK,并同步 1273 个中文客户端资源文件(约 1474 MB)。
设备为 MI 8 Lite / platina、SDM660、Adreno 512、约 4 GB RAM,Android 15 API 35,
LineageOS 22.2-20260103-UNOFFICIAL,GPU Vulkan 1.1.128,OpenGL ES 3.2,4 KB 页。
屏幕 2280×1080 横屏 / 60 Hz;驱动构建日期 2020 年。手机时钟比工作区日期早进一天,CSV 名称保留手机原值。
## 结果
- 正常启动显示中文服务器选择及空账号登录页;软键盘可弹出;应用切后台返回正常。
- 本地模拟登录经过真实客户端登录/选人/加载流程,进入 `metin2_map_a1`,24 只怪物及 4 个其他角色。
- 触控摇杆后角色移动,背包可通过 I 键打开。背包窗口与右侧触控技能按钮重叠,需另行优化遮挡。
- 场景、角色、怪物和背包均显示,渲染可运行,但目前性能不能满足流畅游玩。
- 默认设置(75% 场景分辨率、2x MSAA)8 个两秒采样窗口:约 3.25 FPS,GPU 平均约 312 ms,RSS 约 580 MB。
- 60% 场景分辨率、关闭 MSAA,同场景 8 个两秒采样窗口:约 5 FPS,GPU 平均约 204 ms,RSS 约 594 MB。
- 50% 场景分辨率、关闭 MSAA:静止场景约 6.3–6.4 FPS,GPU 约 157 ms;移动和开背包后场景不同,不用于同场景均值比较。
- 日志显示 GPU 等待远高于脚本/CPU 时间,优先排查地形、多层混合、透明覆盖及片元着色开销,单纯降分辨率不足以达到 30 FPS。
- ROM 的 ADPF PerformanceHint/PowerHAL 不可用,客户端按已有回退路径运行;日志有 AHardwareBuffer 小尺寸探测失败,未阻断此次 Vulkan 启动。
## 修复的闪退
初版 APK 在进入游戏的 `BuildProcessCRC -> GetFileCRC32 -> GetHFILECRC32` 阶段发生 `std::bad_alloc` / SIGABRT。
`GetExcutedFileName` 当前报告工作目录;POSIX `fopen` 可以打开目录,Android 的目录 seek 偏移可能极大,
CRC 文件适配器因此尝试分配异常大的缓冲区。40250 的普通 Win32 文件打开不接受目录。
文件适配层现在先检查 FILE 指向普通文件,拒绝目录/空句柄并检查 seek 错误,普通文件 CRC 和位置保持不变。
`port_utils_test` 通过;审计 `port_map.py check` 为 0 错误。重新构建、安装后两次模拟登录均成功进入地图。
未改变游戏登录协议或绕过 CRC 校验逻辑。
## 范围与后续
这是短时真机功能及性能测试,不是长时间温升或功耗测试(USB 充电中)。
尚未提供游戏测试账号,因此未登录真实服务器,未验证服务器战斗、技能命中、自动狩猎、移动戒指或切地图。
建议下一轮用真实账号复核;性能方面先增加 GPU 分项测试,再处理渲染瓶颈,最后决定低配默认参数。
本次未修改默认画质,手机最终恢复正常登录入口,模拟登录仅由测试启动参数启用。
截图、CSV 和 logcat 位于 `build/qa/xiaomi8lite-20260930/`;APK 位于 `android/app/build/outputs/apk/debug/app-debug.apk`。
+13 -2
View File
@@ -6,6 +6,7 @@
#include <cstdio>
#include <vector>
#include <sys/stat.h>
namespace
{
@@ -107,10 +108,20 @@ DWORD GetHFILECRC32(HANDLE hFile)
{
// 40250 maps the whole file from offset 0 and CRCs it; the stream position is left where it was.
FILE* fp = static_cast<FILE*>(hFile);
// PORT: Win32 CreateFile(FILE_ATTRIBUTE_NORMAL) rejects directories. POSIX fopen does not;
// Android directory seek offsets can be enormous, so reject them before allocating a buffer.
struct stat info{};
if (!fp || fstat(fileno(fp), &info) != 0 || !S_ISREG(info.st_mode))
return 0;
const long pos = std::ftell(fp);
std::fseek(fp, 0, SEEK_END);
if (pos < 0 || std::fseek(fp, 0, SEEK_END) != 0)
return 0;
const long size = std::ftell(fp);
std::fseek(fp, 0, SEEK_SET);
if (size < 0 || std::fseek(fp, 0, SEEK_SET) != 0)
{
std::fseek(fp, pos, SEEK_SET);
return 0;
}
std::vector<char> data(size > 0 ? size : 0);
const size_t got = data.empty() ? 0 : std::fread(data.data(), 1, data.size(), fp);
std::fseek(fp, pos, SEEK_SET);
+7
View File
@@ -111,6 +111,13 @@ int main()
check(GetHFILECRC32(fp) == 0xCBF43926u && ftell(fp) == 4, "GetHFILECRC32 whole file, position kept");
fclose(fp);
check(GetFileCRC32("/nonexistent/mt_crc32") == 0 && GetFileSize("/nonexistent/mt_crc32") == 0, "CRC32 missing file");
check(GetFileCRC32("/tmp") == 0, "CRC32 directory rejected without allocation");
fp = fopen("/tmp", "rb");
if (fp) {
check(GetHFILECRC32(fp) == 0, "CRC32 directory handle rejected");
fclose(fp);
}
check(GetHFILECRC32(nullptr) == 0, "CRC32 null handle rejected");
remove(path);
}