# 长安语言刷入工具 (Changan Language Flashing Tool)

## Overview

A Windows GUI tool suite (Python 3.6+ / tkinter) for flashing multi-language APKs onto Android-based vehicle infotainment systems. Built by 宜宾科宜科技有限公司.

The suite contains **5 tool variants**, each targeting a different vehicle model. All share the same `ADKAPKGUI` class architecture with model-specific customizations. Authorization is VIN-based via a cloud API.

| Tool file | Vehicle | Window title | Pack script |
|-----------|---------|-------------|-------------|
| `app.py` | 启源Q07 | 长安语言安装工具 | `pack_q07.bat` |
| `S05.py` | 深蓝S05 | 深蓝S05多语言安装 | `pack_s05.bat` |
| `X5plusTool.py` | X5plus | 适用于X5plus多语言安装 | `pack_x5plus.bat` |
| `app-install.py` | 长安逸动 (通用) | 长安语言刷入工具 | `pack_common.bat` |
| `app-yidong.py` | 长安逸动 | 长安逸动语言刷入工具 | `pack_yidong.bat` |

## Project structure

```
├── app.py                  # 启源Q07 tool
├── S05.py                  # 深蓝S05 tool
├── X5plusTool.py           # X5plus tool
├── app-install.py          # 逸动通用 tool
├── app-yidong.py           # 逸动 tool
├── pack_q07.bat            # Q07 pack script
├── pack_s05.bat            # S05 pack script
├── pack_x5plus.bat         # X5plus pack script
├── pack_common.bat         # 逸动通用 pack script
├── pack_yidong.bat         # 逸动 pack script
├── test_extract.py         # Standalone test for package.bin extraction
├── app.ico                 # Application icon
├── package.bin             # Encrypted ZIP (not in repo)
├── adb.exe                 # Bundled ADB
├── AdbWinApi.dll           # ADB dependency
├── AdbWinUsbApi.dll        # ADB dependency
└── .vscode/
    └── settings.json
```

## Architecture

### Single-file design

Each tool is a single Python file under the `ADKAPKGUI` class. No MVC separation — the class handles GUI, business logic, ADB operations, network calls, and file extraction.

### Threading model

- **Main thread**: tkinter event loop (`root.mainloop()`)
- **Background threads**: All user-triggered operations spawn `threading.Thread(target=..., daemon=True)`
- **Thread-safety**: UI mutations via `self.run_on_ui_thread(func, ...)` → `self.root.after(0, func, ...)`. Internal `_impl` methods are the actual tkinter-touching implementations.

### ADB operations

- `run_adb_command(command)` — standard ADB commands; auto-substitutes `adb` with bundled `adb.exe` path when frozen
- `run_adb_shell(shell_command)` — only in app-install.py / app-yidong.py; shells into device with auto-password `adb36987`

ADB path is portable: `self.adb` resolves to `sys._MEIPASS/adb.exe` when frozen (PyInstaller bundle), or `'adb'` in development.

### Authentication flow

1. ADB detects device → reads VIN (`ca_vin_info` or `VIN`; 逸动 uses `ca.car.vin`)
2. VIN sent to `https://api.changan.softwindy.cn/api/authorizations/auth-check?vin=...`
3. Package password from `https://api.changan.softwindy.cn/api/authorizations/package-key?vin=...`
4. Password used to decrypt `package.bin`

### Package extraction

- `package.bin` is a password-protected ZIP (AES via pyzipper, fallback to zipfile)
- Extracted to `%LOCALAPPDATA%\.cache\system\.android\apps_cache_{variant}` (hidden via `attrib +h`)
- Each tool has its own cache folder to avoid conflicts:
  - app.py → `apps_cache_Q07`
  - S05.py → `apps_cache_S05`
  - X5plusTool.py → `apps_cache_X5plus`
  - app-install.py → `apps_cache_common`
  - app-yidong.py → `apps_cache_common` (default)
- Extracted APKs in `app/` pushed to `/system/app/`, `priv-app/` to `/system/priv-app/`

### Device status monitoring

Background daemon thread runs `adb devices` every 5 seconds to detect connect/disconnect events.

## GUI layout (650x640 dark theme for most; 650x550 for 逸动)

| Section | Contents |
|---------|----------|
| Title bar | Vehicle model + company subtitle |
| Password query | Hidden VIN→password lookup (S05, app-install only) |
| Button row 1 | 获取权限 (Q07/S05), 刷入语言包, 安装App, 语言设置 |
| Button row 2 | 时区设置, 安卓设置, 重启设备, 禁用升级 |
| Status bar | Connection dot, VIN, Auth status, Refresh button |
| Tips | Usage warnings |
| Progress | Extraction + push progress (hidden by default) |
| Log area | ScrolledText with tags (INFO/SUCCESS/ERROR/WARNING/CMD), 清空日志 button in title bar |

## Key features

### Install App (unified single/batch)
"安装App" button uses `filedialog.askopenfilenames` for multi-file selection, replacing old separate "单个安装" and "批量安装" buttons. Select 1 or more APKs and installs all in one pass (`adb install -r`).

### Debug mode (hidden)
Press `Ctrl+Shift+D` → password `zxch5200` to enter debug mode:
- Bypasses device connection and authorization checks (UI shows "已连接" / "已授权")
- Logs all raw ADB commands and output to the log panel
- Exiting debug mode auto-refreshes real device state

### Language quick-set
Popup with 8 one-click locale switches (zh-CN, en-US, ru-RU, fr-FR, es-ES, pt-BR, it-IT, ar-SA). Also links to native Android language settings. Changes take effect after reboot.

### Model-specific behaviors

| Feature | Q07 (app.py) | S05 (S05.py) | X5plus (X5plusTool.py) | 逸动 (app-install/yidong) |
|---------|-------------|-------------|------------------------|---------------------------|
| Root perm | Y | Y | N (no btn_root) | N |
| priv-app | Y | Y | Y | N (app only) |
| ADB shell | Standard | Standard | Standard | Auto-password `adb36987` |
| VIN key | ca_vin_info/VIN | ca_vin_info/VIN | ca_vin_info/VIN | ca.car.vin |
| Old app cleanup | N | N | Y (5 packages) | N |
| Font push | N | N | Y (FZLTHPro) | N |
| Overlay enable | N | N | N | N (removed) |
| Password query | N | Y | N | Y |
| Factory hints | N | Y | Y (dynamic pwd) | Y |

## Build process

Each `pack_*.bat` follows the same pipeline:
1. Install deps: `pyinstaller`, `cython`, `pyzipper`
2. Clean old build dirs
3. Cython compile: `{source}.py` → `_core.pyd`
4. Copy resources: `adb.exe`, DLLs, `app.ico`
5. PyInstaller: single `.exe` with `--uac-admin`, bundling `_core.pyd` + ADB + DLLs
6. Fallback to normal PyInstaller if Cython fails

Output exe is self-contained — bundles `adb.exe` and DLLs via `sys._MEIPASS`, no external ADB needed.

## Key behaviors to preserve

1. **Thread safety**: Never call tkinter from background threads — always use `run_on_ui_thread`
2. **VIN-based auth**: Authorization required before push; flow must remain intact
3. **Silent extraction**: Auto-extract `package.bin` without user step
4. **ADB portability**: `self.adb` resolves to bundled exe path; all commands go through `run_adb_command`
5. **vecentek.model**: Set to 1 before install, 0 after
6. **Chinese encoding**: `# -*- coding: utf-8 -*-` throughout
7. **Debug mode**: `self.debug_mode` flag gates auth/connection bypass and verbose logging
8. **Separate cache dirs**: Each tool extracts to its own cache folder

## Known issues

- `test_extract.py` hardcodes password — should fetch from API
- `on_disable_upgrade` uses `findstr` (Windows-specific)
- Exception handling is minimal in many places (bare `except: pass`)
- 逸动 tools (app-install/yidong) use `subprocess.Popen` with stdin password injection — fragile
