Files
2026-07-07 14:37:04 +08:00

285 lines
29 KiB
Markdown

# 长安语言刷入工具 (Changan Language Flashing Tool)
## Overview
Windows GUI tool suite (Python 3.6+ / tkinter) for flashing or pushing multi-language APKs to Android-based vehicle infotainment systems. Built by 宜宾科宜科技有限公司.
Most tools are single-file tkinter apps with the same rough architecture: GUI, VIN authorization, package extraction, ADB commands, logging, and worker threads live in one class. Preserve that style unless the user explicitly asks for a larger refactor.
## Tool Variants
| Tool file | Vehicle / purpose | Window title | Pack script |
|-----------|-------------------|--------------|-------------|
| `Q07/Qiyuan_Q07-multi-lan-installer.py` | 启源Q07 | 适用于启源Q07多语言安装 | `Q07/pack_q07.bat` |
| `S05/S05.py` | 深蓝S05 original | 深蓝S05多语言安装 | `S05/pack_s05.bat` |
| `S05/S05_fixed.py` | 深蓝S05 fixed/experimental copy | 长安语言安装工具 | `S05/pack_s05_fixed.bat` |
| `X5plus/X5plusTool.py` | X5plus | 适用于X5plus多语言安装 | `X5plus/pack_x5plus.bat` |
| `CS55-Q05/CS55-Q05_Installer.py` | CS55Plus/Q05 通用 | CS55Plus/Q05 语言刷入工具 | `CS55-Q05/pack_cs55_q05.bat` |
| `CS75Pro/CS75Pro_Installer.py` | CS75Pro | CS75Pro 语言刷入工具 | `CS75Pro/pack_cs75pro.bat` |
| `Yidong/app-yidong.py` | 长安逸动 | 长安逸动语言刷入工具 | `Yidong/pack_yidong.bat` |
| `UNIZ/UNIZ.py` | UNI-Z file pusher | UNI-Z语言文件推送工具 | `UNIZ/pack_uniz.bat` |
| `UNI-T/UNI-T-multi-lan-installer.py` | UNI-T | 适用于UNI-T多语言安装 | `UNI-T/pack_unit.bat` |
| `Mazda-EZ60/Mazda-EZ60_1.2.py` | Mazda-EZ60 OS 1.2 | Mazda-EZ60_OS-1.2适用 | `Mazda-EZ60/pack_mazda_ez60_1.2.bat` |
| `Mazda-EZ60/Mazda_EZ60-Language-Install_v1.0.py` | Mazda-EZ60 OS 1.0 | 马自达EZ60刷机工具_OS-1.0 | `Mazda-EZ60/pack_mazda_ez60_1.0.bat` |
| `Q05-Lidar/Q05-Lidar_Installer.py` | Q05_Lidar permission/bootstrap + language installer | Q05_Lidar | `Q05-Lidar/pack_q05_lidar.bat` |
## Project Structure
```
├── Q07/ # Q07 script, pack scripts, ignored build outputs
├── S05/ # S05 original and fixed copy
├── X5plus/ # X5plus tool
├── CS55-Q05/ # CS55Plus/Q05 common installer and icon
├── CS75Pro/ # CS75Pro installer copied from CS55-Q05 flow
├── Yidong/ # Yidong-specific tool
├── UNIZ/ # UNI-Z file pusher
├── UNI-T/ # UNI-T installer cloned from Q07 flow
├── Mazda-EZ60/ # Mazda-EZ60 tool
├── A07/ # Qiyuan A07 tool
├── Q05-Lidar/ # Q05_Lidar tool plus resource.dat/tools
├── app.ico
├── package.bin # encrypted package, not committed; shared from root
└── tools/ # shared adb/fastboot/7za dependencies for pack scripts
├── adb.exe
├── AdbWinApi.dll
├── AdbWinUsbApi.dll
├── fastboot.exe
└── 7za.exe # 7-Zip Extra 26.01, bundled by pack scripts
```
## Architecture Notes
- Most tools use class `ADKAPKGUI`; `UNIZ/UNIZ.py` uses `UNIZLanguageGUI`.
- Worker actions run in `threading.Thread(..., daemon=True)`.
- Tkinter calls from workers must go through `run_on_ui_thread(...)`.
- Prefer `self.root.after(0, lambda: func(*args, **kwargs))` in `run_on_ui_thread`; direct `after(0, func, *args, **kwargs)` breaks when kwargs such as `text=` or `fg=` are passed.
- Background `messagebox.*` calls should be scheduled with `run_on_ui_thread`.
- Keep files UTF-8 with `# -*- coding: utf-8 -*-`.
## ADB And Auth
- `run_adb_command(command)` handles normal ADB commands such as `adb devices`, `adb push`, and non-shell install calls.
- `run_adb_shell(shell_command)` exists in the 逸动-family tools and Mazda copy; it shells into the device and automatically sends password `adb36987`.
- All `adb shell` operations in `CS55-Q05/CS55-Q05_Installer.py`, `CS75Pro/CS75Pro_Installer.py`, `Yidong/app-yidong.py`, and `Mazda-EZ60/Mazda-EZ60_1.2.py` should go through `run_adb_shell()`.
- `UNIZ/UNIZ.py` must not use `adb shell`; it only checks devices and pushes APKs to `/storage/emulated/0/Download/`.
- Standard auth flow uses:
- `auth-check?vin=...` for authorization.
- `package-key?vin=...` for `package.bin` extraction password.
- VIN keys:
- Q07/S05/X5plus: `ca_vin_info` or `VIN`.
- UNI-T: try `persist.vendor.car.VIN`, then `settings get global VIN`, then legacy system VIN keys.
- 逸动/Mazda: `settings get system ca.car.vin` via auto-password shell.
- UNI-Z: user manually enters VIN.
## Package Extraction
- `package.bin`-style encrypted resources are extracted under `%LOCALAPPDATA%\.cache\system\.android\...`.
- Current cache directories:
- `Q07/Qiyuan_Q07-multi-lan-installer.py` -> `apps_cache_Q07`
- `S05/S05.py` / `S05/S05_fixed.py` -> `apps_cache_S05`
- `X5plus/X5plusTool.py` -> `apps_cache_X5plus`
- `CS55-Q05/CS55-Q05_Installer.py` -> `apps_cache_common`
- `CS75Pro/CS75Pro_Installer.py` -> `apps_cache_CS75Pro`
- `Yidong/app-yidong.py` -> `apps_cache_yidong`
- `UNIZ/UNIZ.py` -> `apps_cache_UNIZ`
- `UNI-T/UNI-T-multi-lan-installer.py` -> `apps_cache_UNI_T`
- `Mazda-EZ60/Mazda-EZ60_1.2.py` -> `apps_cache_Mazda_EZ60`
- Shared binaries are managed under root `tools/`: `adb.exe`, `AdbWinApi.dll`, `AdbWinUsbApi.dll`, `fastboot.exe`, and `7za.exe`. Vehicle pack scripts in subfolders should copy from `%ROOT%\tools`, not from each vehicle folder.
- For progress display, detect support for `-bsp1` by checking for `-bs{o|e|p}` in 7za help output.
- If `Incorrect command line` appears, retry with the basic compatible command: `x PACKAGE -pPASSWORD -oDIR -y`.
- Decode 7za output with GBK first, then UTF-8 fallback.
- 7za progress must parse streamed output cumulatively. Do not read one byte and regex that single byte; percentages such as `42%` span multiple bytes and will otherwise jump from 0 to 100.
- User-facing resource extraction text should say `资源准备中` / `Preparing resources`, not `资源解压` / `Extracting package`, unless the UI is an explicit debug test.
- Cache cleanup should be best effort in three places when feasible: before a new extraction, during normal window close, and via `atexit` for ordinary process exit. A forced process kill cannot be guaranteed, so also clear stale caches at next extraction/startup.
## Shared UX And Safety Rules
- Hosts update logic should replace conflicting entries for the managed domain. If the hosts file already contains the target domain with a different IP, delete that line and write the expected `IP domain` entry instead of appending duplicates.
- VIN authorization logs should be explicit for operator-facing flows: print the current VIN, print `data.vehicleName` when `auth-check` returns it, print authorization success, and print a clear unauthorized/failure log when denied.
- `package-key` requests should use the vehicle name returned by `auth-check` (`data.vehicleName`) whenever available. Do not hardcode a model name if the authorization API already returned the exact vehicle name for the VIN.
- Normal users should not see low-level sensitive process details such as `fastboot`, `init_boot`, boot keys, or image names during permission/bootstrap flows. Use black-box text such as `正在获取权限中`, `获取成功`, and `获取失败`; leave command details for debug mode only.
- Process logs should stay minimal in normal mode. Detailed ADB/7za/API command logs belong behind debug mode.
- All Tkinter UI updates and `messagebox.*` calls from workers must go through `run_on_ui_thread(...)`.
## Model-Specific Behavior
### Q07
- Main script is `Q07/Qiyuan_Q07-multi-lan-installer.py`; keep `Q07/app.py` retired unless explicitly asked to restore the old name.
- Q07 release resource package is `Q07_package.bin`, not shared root `package.bin`. The tool may keep a compatibility fallback for old local `package.bin`, but user-facing errors/logs should name `Q07_package.bin`.
- Q07 cache directory is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_Q07`. Clean it before extraction, on normal window close, and through `atexit`.
- Q07 `package-key` requests must include both `vin` and `vehicleName`; `vehicleName` comes from `auth-check` (`data.vehicleName`) and should be cached when available.
- Q07 `安装App` must also verify the current VIN is authorized before installing selected APK files. Debug mode may skip this check; normal mode must not.
- Q07 debug mode uses `Ctrl+Shift+D` and verifies the password through `POST /api/authorizations/verify-debug-mode-password`; do not restore hardcoded local debug passwords.
- Q07 debug mode exposes `解压测试` / `Ctrl+Shift+E`; it fetches `package-key` and extracts `Q07_package.bin`. The success log should only say `资源准备完成` / `Resources ready`, not app or priv-app counts.
- Q07 normal logs should keep the resource structure black-box: do not show app/priv-app counts or the current APK name during `刷入语言包`. `安装App` may show the selected APK filename currently being installed.
- Q07 UI has only language switching. Do not reintroduce dark/light theme switching or company/about subtitle text.
- Q07 window/taskbar icon should use `Q07/app.ico` at runtime: call `iconbitmap`, set a Windows AppUserModelID before creating `Tk()`, and set big/small Win32 window icons when possible. The pack scripts must include `--icon="%ICON%"` and `--add-data "%ICON%;."`.
- Q07 pack scripts (`Q07/pack_q07.bat` and `Q07/pack.bat`) are Cython-only. If Cython fails or no `_core*.pyd` is generated, stop with an error; do not fallback to normal PyInstaller.
- Q07 pack scripts use ASCII output name `Qiyuan_Q07-multi-lan-installer`, compile `Qiyuan_Q07-multi-lan-installer.py` into `_core.pyd`, use a tiny launcher, and bundle `adb.exe`, `AdbWinApi.dll`, `AdbWinUsbApi.dll`, `7za.exe`, and `Q07/app.ico`.
### S05
- Keep `S05/S05.py` as original unless explicitly asked.
- Use `S05/S05_fixed.py` for experimental/fixed S05 changes.
- Do not add `chmod`, `chown`, or `restorecon` to the S05 system-app push path unless explicitly requested; the target system inherits permissions.
- `S05/S05_fixed.py` includes debug extract test `Ctrl+Shift+E` and 7za progress support.
### UNI-Z
- Endpoint for visible passwords: `/api/authorizations/get-uni-z-pwd`.
- Display `factoryPwd` as factory mode password and `password` as debug password.
- If `authorized == false` or `password` is empty, show unauthorized state and do not proceed.
- `password` from `get-uni-z-pwd` is not the package extraction password.
- Before push, call `/api/authorizations/package-key?vin=...` to get the real `package.bin` password.
- Push only to `/storage/emulated/0/Download/`; no `adb shell`.
- Language selection: RU/FR/ES/EN. Only the selected language Settings APK is pushed; other language Settings APKs are skipped silently.
- Hidden debug mode: `Ctrl+Shift+D`, password `zxch5200`, logs full ADB/7za/API details.
### UNI-T
- Main script is `UNI-T/UNI-T-multi-lan-installer.py`; it is cloned from the Q07 installer flow and preserves Q07-style VIN authorization, package extraction, system app push/install logic, language settings, debug password verification, and Cython-only packaging.
- UNI-T VIN should be read with fallbacks: `adb shell getprop persist.vendor.car.VIN`, then `settings get global VIN`, then legacy `settings get system VIN` / `settings get system ca_vin_info`. On the connected S202_MCA device, the live VIN is currently in `settings global VIN`.
- UNI-T `获取权限` must run `adb shell setenforce 0` before `adb root` and `adb remount`; without this pre-step, `adb root` may not open on this vehicle.
- UNI-T release resource package is `UNI-T_package.bin`, with legacy `package.bin` fallback only for local compatibility. User-facing errors/logs should name `UNI-T_package.bin`.
- UNI-T cache directory is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_UNI_T`. Clean it before extraction, on normal window close, and through `atexit`.
- Before UNI-T `刷入语言包` pushes files, run `pm disable-user --user 10` for: `com.wt.roadbook`, `com.thunder.carplay`, `com.tencent.wecarmas`, `com.tencent.qqlive.audiobox`, `com.incall.apps.softmanager`, `com.changan.appmarket`, and `com.bytedance.byteautoservice`.
- UNI-T package root may contain `CarSystemUI.apk`; during `刷入语言包`, push it separately and copy it with `cp -f` to `/system/system_ext/priv-app/CarSystemUI/CarSystemUI.apk`.
- UNI-T `package-key` requests must include both `vin` and `vehicleName`; `vehicleName` comes from `auth-check` (`data.vehicleName`) and should be cached when available.
- `UNI-T/pack_unit.bat` is Cython-only. If Cython fails or no `_core*.pyd` is generated, stop the build; do not fallback to normal PyInstaller.
### CS55-Q05
- CS55Plus/Q05 common installer lives in `CS55-Q05/CS55-Q05_Installer.py`, with icon `CS55-Q05/cs55-q05.ico` and pack script `CS55-Q05/pack_cs55_q05.bat`.
- `pack_cs55_q05.bat` is Cython-only. If Cython fails or no `_core*.pyd` is generated, stop the build; do not fall back to normal PyInstaller.
- `刷入语言包` must verify VIN authorization before resource flashing. After authorization passes and before APK flashing, run both `pm disable-user <package>` and `pm uninstall -k --user 0 <package>` through `run_adb_shell()` for `com.wtcl.electronicdirections`, `com.tinnove.netease.music`, and `com.changan.appmarket`.
- All CS55/Q05 language package and manual APK installs should use `pm install -d -f -r <apk>` through `run_adb_shell()` so older/different app versions can install reliably.
- After CS55/Q05 language flashing or APK installation, do not reset `setprop vecentek.model` back to `0`; keep it at `1` so users can continue installing APKs manually.
- Normal `刷入语言包` logs should not reveal APK names; show generic current/total progress only. `安装App` may show each APK result and current APK name.
### CS75Pro
- CS75Pro installer lives in `CS75Pro/CS75Pro_Installer.py`, copied from the CS55-Q05 flow, with icon `CS75Pro/cs75pro.ico` and pack script `CS75Pro/pack_cs75pro.bat`.
- Keep the CS75Pro flashing flow aligned with CS55-Q05 unless explicitly requested.
- CS75Pro cache directory is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_CS75Pro`.
- CS75Pro `package-key` requests must include both `vin` and `vehicleName`, but `vehicleName` is intentionally hardcoded to `CS75Pro`. This is an explicit exception to the general auth-returned `vehicleName` rule; do not replace it with `auth-check` `data.vehicleName` in future edits.
- Before CS75Pro `刷入语言包`, run `pm disable-user <package>` first and then `pm uninstall -k --user 0 <package>` through `run_adb_shell()` for `com.wtcl.electronicdirections`, `com.tinnove.netease.music`, `com.incall.apps.softmanager`, and `com.tencent.qqlive.audiobox`.
- CS75Pro language package installs should use `pm install -d -f -r <apk>` through `run_adb_shell()`.
### Mazda-EZ60
- Based on `CS55-Q05/CS55-Q05_Installer.py` / 逸动 flow.
- Uses auto-password shell (`adb36987`) for VIN reads, `pm install`, overlay enable, disable commands, settings, and reboot.
- Installs APKs from extracted `apps` via push to `/data/local/tmp` then `pm install -r -d`.
- `Mazda-EZ60/Mazda-EZ60_1.2.py` should show 7za extraction progress with stream parsing.
- Mazda 1.2 resource package is `package_voice-assistant.bin`, not the old `package.bin`; `package-key` still supplies the extraction password.
- Mazda 1.2 package cache is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_Mazda_EZ60`; clean it on startup, before extraction, on normal window close, and through `atexit`.
- Mazda `package-key` requests must include both `vin` and `vehicleName`; cache `data.vehicleName` from `auth-check`, and query `auth-check` before `package-key` if it is missing.
- Mazda 1.2 has a first-row `语音助理补丁` button that installs Magisk modules from the same extracted package. The package should contain `enable_install.zip` and `MazdaEZ60VoiceEnglish-1.2-Aemeth.zip` beside `apps/` (the tool also tolerates them inside `apps/`), and each zip must contain a valid `module.prop`.
- Mazda 1.2 `获取权限` uses a separate `boot-challenge` -> `boot-key` flow and must only use `data.sessionKey` / BOOT_KEY to decrypt `EZ60_resource.dat`; do not reuse `package-key` as the init_boot resource key.
- Mazda 1.2 `EZ60_resource.dat` is an AES-256-GCM init_boot resource with `EZ60R2` header / `ez60-resource-v2` format and default AAD `Mazda-EZ60 init_boot resource v1`. Generate it with `tools/encrypt_q05_lidar_resource.py --vehicle ez60 -o EZ60_resource.dat ...` using the EZ60 patched `init_boot.img`.
- Mazda 1.2 `EZ60_resource.dat` is optional at build time: `pack_mazda_ez60_1.2.bat` should embed it into the exe only when the file exists, and should not fail the build when it is absent. The permission feature still needs it at runtime to complete init_boot flashing.
- Mazda 1.2 `获取权限` follows the Q05_Lidar bootstrap shape: extract `runtime.dat` to `base.apk` using the package-key password when needed, run `setprop vecentek.model 1` through `run_adb_shell()` so the `adb36987` auto-password is sent, push/install `base.apk`, then fetch the boot key, reboot to fastboot through `run_adb_shell('reboot fastboot')`, wait for a real `<serial> fastboot` row, flash `init_boot`, immediately reboot, clear the temporary img, and keep normal logs black-box (`正在获取权限中` / `获取成功` / `获取失败`).
- Mazda 1.2 `runtime.dat` is copied next to the release exe by `pack_mazda_ez60_1.2.bat`, and its temporary cache is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_Mazda_EZ60_runtime`.
- Mazda 1.2 detects the bootloader driver environment like Q05_Lidar. If missing, prompt once and install automatically; keep a manual `安装驱动` button in the status bar. Bundle `tools/usb_driver/` into the onefile exe via PyInstaller `--add-data`, resolving it from `_MEIPASS` at runtime.
- After Mazda 1.2 voice patch root authorization succeeds, clean the Magisk manager/stub launcher entry with the tested `pm uninstall -k com.topjohnwu.magisk` path first, then optional per-user uninstall/disable and manager/stub apk cache cleanup. Because the icon can reappear after reboot, also install a tiny Magisk module under `/data/adb/modules/ez60_magisk_manager_cleanup` whose `service.sh` repeats the same manager/stub cleanup after boot. Do not remove `/data/adb/modules` or the voice modules.
- `Mazda-EZ60/Mazda_EZ60-Language-Install_v1.0.py` is the exception: its `package-key` `vehicleName` is fixed to `EZ60_1.0`. Do not replace it with the authorization-returned vehicle name.
- Mazda hosts setup should keep exactly one target mapping for `spm.auto-pai.com`: replace mismatched IPs with `103.236.55.140 spm.auto-pai.com` instead of appending a conflicting duplicate. If hosts setup fails, tell the user `环境配置失败`.
- Mazda UI should not show the company/about subtitle.
- Mazda language switching should cover all operator-facing buttons, labels, dialogs, logs, progress text, hotspot status, password query UI, and quick-language popup text. The right-side usage tips should render from translated `hint_lines` with wrapping so English text does not overlap or overflow.
- Mazda normal logs/prompts should keep only key operator-facing outcomes and fuzzy resource/environment errors. Do not show package names, language package APK names, raw commands, paths, or command output during `刷入语言包`; manual `安装App` may show selected APK filenames. VIN and `vehicleName` are not sensitive and may remain visible.
- Mazda debug mode uses `Ctrl+Shift+D` and verifies the password through `POST /api/authorizations/verify-debug-mode-password`; detailed ADB/7za/API output belongs in debug mode only.
- Mazda pack scripts `pack_mazda_ez60_1.0.bat` and `pack_mazda_ez60_1.2.bat` are Cython-only. If dependencies, Cython compilation, PYD generation, resource copy, PyInstaller, or final exe output fail, stop immediately with an `[ERROR]` reason; do not fall back to normal PyInstaller.
- Regardless of APK install failures, run post-install configuration after the install loop.
- Post-install overlays to enable:
- `com.tinnove.launcher.overlay`
- `com.tinnove.scenemode.overlay`
- `com.incall.dvr.overlay`
- Post-install packages to disable:
- `com.carinno.p1`
- `com.wtcl.electronicdirections`
- `com.ximalaya.ting.android.car`
- `com.tinnove.netease.music`
- `com.migu.miguplay.car`
- `cn.cmvideo.car.play`
- `com.tinnove.carshow`
- `com.tinnove.changba`
- `com.qiyi.video.iv`
- User cancelled the `Ctrl+Shift+E` direct extract test request for Mazda; do not add it unless asked again.
### Q05_Lidar
- This is the Q05_Lidar-specific tool and must not be confused with any ordinary Q05 variant or package.
- Based on the shared installer visual style, but its resource structure and flashing flow are Q05_Lidar-specific.
- The first-row `获取权限` button installs `runtime.dat` -> `base.apk`, reboots to fastboot, waits for a real `fastboot devices` row like `<serial> fastboot` with a non-aggressive interval, then fetches a boot key through `POST /api/authorizations/boot-challenge` then `POST /api/authorizations/boot-key`, decrypts embedded `resource.dat`, flashes `init_boot`, immediately reboots, and deletes the temporary img. Keep the decrypted img lifetime as short as possible.
- `resource.dat` is AES-GCM encrypted and must match the server `BOOT_KEY`; the tool only accepts `data.sessionKey` from `boot-key`.
- Device fingerprint data sent to the server includes ADB serial, `ro.serialno`, `ro.boot.serialno`, manufacturer, model, device, build fingerprint, and VIN.
- `刷入语言包` installs Magisk modules, not APKs. It opens `com.topjohnwu.magisk`, warns the user to grant Shell/root permission, verifies `/debug_ramdisk/su -c "id"` returns `uid=0`, silently uninstalls `com.topjohnwu.magisk` for user 0, extracts `Q05_Lidar-package.bin`, reads each module zip's root `module.prop` on the PC to get `id=`, pushes each zip to `/data/local/tmp/q05_lidar_modules/<MODID>.zip`, then root-unzips it into `/data/adb/modules/<MODID>`.
- If Magisk shows its first-run environment repair/additional setup prompt, do not automate UI clicking in the tool; the operator should confirm it manually and reboot once before retrying.
- Before installing Q05_Lidar language resources, disable OTA with `pm disable-user com.incall.apps.softmanager`, then for `com.carcontrolhome.app`, `com.tinnove.netease.music`, and `com.wtcl.electronicdirections` run both `pm disable-user <package>` and `pm uninstall --user 0 <package>`. These commands must go through `run_adb_shell()`.
- `Q05_Lidar-package.bin` should unpack to module zip files, preferably under `modules/`, for example `modules/Qiyuan_Q05-multi_lan.zip` and `modules/disable_wireless_adb_vecentek.zip`. Each module zip must contain `module.prop` at zip root, plus scripts and `system/` as needed. Do not wrap `module.prop` inside an extra outer folder.
- Q05_Lidar package cache is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_Q05_Lidar`; the tool cleans it on startup/extraction and on normal/atexit shutdown.
- Q05_Lidar `runtime.dat` cache is `%LOCALAPPDATA%\.cache\system\.android\apps_cache_q05_lidar_runtime`; treat it as temporary and clean stale contents before extraction.
- `Q05_Lidar-package.bin` is an external release file next to the exe because it is large. `resource.dat` is embedded in the exe; `runtime.dat` should be copied next to the exe by the pack script.
- Q05_Lidar checks driver environment on startup. If the driver environment already exists, stay silent and do not log a success/info message for the operator.
- If the startup check finds the driver environment missing, show a single simple prompt such as `驱动缺失,即将自动安装驱动。`; after the user clicks confirm, start installation immediately. Do not show a second `是否继续` confirmation in that startup flow.
- User-facing driver logs/prompts should say only `驱动环境` / `Driver environment`; do not mention `USB/Fastboot` or `Android/Fastboot`.
- Manual `安装驱动` remains available in the status bar, but `检查` should appear before it visually because it is more directly related to device status/refresh actions.
- `usb_driver/` is bundled inside the Q05_Lidar onefile exe via PyInstaller `--add-data`, and runtime driver installation should resolve files from the extracted temporary resource directory (for frozen builds, `_MEIPASS`) instead of requiring a sidecar `usb_driver` folder next to the exe.
- `package-key` must include the `vehicleName` returned by `auth-check` for the VIN. The tool caches `data.vehicleName` from password query / authorization check and uses it for package-key; if missing, query `auth-check` first rather than falling back to a hardcoded Q05_Lidar value.
- All `adb shell` commands in Q05_Lidar, including Magisk launch and `/debug_ramdisk/su -c ...`, must go through `run_adb_shell()` so the tool silently sends `adb36987`.
- The `安装App` button remains the APK install path: file picker -> `adb push` -> `setprop vecentek.model 1` -> `pm install -r -d -f` -> cleanup. Do not replace it with the Magisk module flow.
- Temporary debug mode exists only for development and should be removed before release when requested. Press `Ctrl+Shift+D`; the password is verified through `POST /api/authorizations/verify-debug-mode-password`.
- In Q05_Lidar debug mode, hidden buttons appear for:
- `指纹测试`: collect and log device fingerprint fields plus local SHA256 summary.
- `解密测试`: if VIN/device is available, fetch boot key; otherwise prompt for a pasted `BOOT_KEY`/`sessionKey`, decrypt `resource.dat` locally to a temporary img, log size/SHA256, then delete it.
- `解压测试`: fetch `package-key`, extract `Q05_Lidar-package.bin`, and verify the main Magisk module plus `disable_wireless_adb_vecentek` module can be identified.
- Do not log the actual boot key/session key in debug mode.
### Yidong/app-yidong.py
- Uses `apps_cache_yidong`.
- Has 7za compatibility handling for progress switches and `Incorrect command line` fallback.
- `Yidong/pack_yidong.bat` output name is ASCII: `Changan-Yidong-Language-Installer.exe`, to avoid CMD codepage issues with Chinese `NAME`.
## Build Notes
- Pack scripts install/use `pyinstaller`, `cython`, and usually `pyzipper`.
- Cython success requires Microsoft C++ Build Tools.
- Cython success signs in logs:
- `building '_core' extension`
- `_core.cpXXX-win_amd64.pyd`
- `PYD: _core...pyd`
- output under `dist_cy\dist\...exe`
- If logs show `[WARN] Cython failed, fallback` and `[INFO] Normal PyInstaller`, the exe still builds but is normal PyInstaller and easier to reverse.
- For security-sensitive tools like Q05_Lidar and Q07, do not keep a normal PyInstaller fallback. If Cython fails or no `_core*.pyd` is generated, stop the build and show an error.
- A Cython onefile PyInstaller build should use a tiny `launcher.py` that imports `main` from compiled `_core.pyd`, and the exe archive should contain `_core*.pyd`. Confirm with PyInstaller archive viewer when in doubt.
- `UNIZ/pack_uniz.bat` and Mazda-EZ60 pack scripts use ASCII output names to avoid CMD encoding problems.
- Generated `.exe`, `.spec`, `build/`, `dist/`, and `dist_cy/` are build artifacts and should not be committed unless explicitly requested.
## Key Behaviors To Preserve
1. Keep original tools untouched when a fixed or model-specific copy exists.
2. Preserve VIN-based authorization for normal flashing tools.
3. Fetch `package-key` from the server instead of hardcoding package passwords.
4. Keep all shell commands in 逸动/Mazda tools behind `run_adb_shell()`.
5. Keep UNI-Z shell-free.
6. Use `run_on_ui_thread()` for all tkinter UI updates from worker threads.
7. Keep shared Android/7za binaries under root `tools/` and have pack scripts copy from there.
## Current Local State (2026-05-28)
- `UNIZ/UNIZ.py` and `UNIZ/pack_uniz.bat` exist locally. Cython build has succeeded after installing Microsoft C++ Build Tools, producing `dist_cy\dist\UNIZ-Language-Pusher.exe`.
- `Mazda-EZ60/Mazda-EZ60_1.2.py` with `pack_mazda_ez60_1.2.bat`, and `Mazda-EZ60/Mazda_EZ60-Language-Install_v1.0.py` with `pack_mazda_ez60_1.0.bat`, exist locally. Mazda has 7za progress extraction, Cython-only packaging, and version-specific output names.
- `Yidong/app-yidong.py` has been updated for 7za progress compatibility and `Incorrect command line` fallback.
- `Yidong/pack_yidong.bat` has been updated with quoted paths, `cd /d "%~dp0"`, and ASCII output name.
- `.gitignore` has been expanded to ignore generated exe/spec artifacts.
- There may be untracked local build outputs and generated specs; inspect `git status --ignored` before committing.
## Known Issues
- Some older tools still have minimal exception handling and bare `except: pass`.
- `test_extract.py` hardcodes a password and should not be treated as production flow.
- `on_disable_upgrade` behavior is Windows/vehicle specific.
- Pure PyInstaller fallback is easy to reverse; prefer successful Cython builds for release.