Fix Android directory CRC login crash and record Mi 8 Lite device tests
This commit is contained in:
@@ -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"}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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`。
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user