# Methodology & Sources ## How This Documentation Was Obtained All information in this documentation was extracted through **static analysis of the decompiled DWARFLAB Android APK** (v3.4.0, build 629, package `com.convergence.dwarflab`). No device was needed — the entire protocol is defined in the app's code. ### Decompilation The APK was decompiled using **apktool v3.4.0**, which produced: - `AndroidManifest.xml` — permissions, activities, services - `smali/` through `smali_classes7/` — 7 DEX files of dalvik bytecode - `lib/` — native `.so` libraries (arm64, armeabi-v7a, x86_64) - `assets/` — voice JSON, country JSON, keystores - `res/` — layouts, drawables, Lottie animations ### Key Smali Files Mapped to Protocol Concepts | Protocol Concept | Smali File | Location | |-----------------|------------|----------| | BLE UUIDs | `cg1.smali` | `smali_classes4/` | | BLE commands | `j80.smali` | `smali_classes4/` | | BLE packet format | `l80.smali` | `smali_classes4/` | | BLE CRC-16 | `vc0.smali` | `smali_classes4/` | | WebSocket URL | `v55.smali` | `smali_classes4/` | | WsPacket fields | `BaseProto$WsPacket.smali` | `smali_classes5/` | | WsModuleId | `WsModuleId.smali` | `smali_classes4/` | | WsCmd (all commands) | `WsCmd.smali` | `smali_classes4/` | | WsMessageType | `WsMessageType.smali` | `smali_classes4/` | | WsRespCode | `WsRespCode.smali` | `smali_classes4/` | | DeviceType | `DeviceType.smali` | `smali_classes4/` | | BluetoothPacketSender | `BluetoothPacketSender.smali` | `smali_classes4/` | | ConnectionManager | `ConnectionManager.smali` | `smali_classes4/` | | Proto messages | `AstroProto*.smali`, `CameraProto*.smali`, etc. | `smali_classes5/` | ### Extraction Methods #### 1. UUID Discovery (`cg1.smali`) The `cg1` class contains 8 static UUID strings. Read directly from the `` method — the values are string constants embedded in the bytecode. #### 2. Command IDs (`WsCmd.smali`) The `WsCmd` enum contains ~300 entries. Each entry is initialized in `` via `(String name, int ordinal, int cmd)`. The third parameter (`cmd`) is the numeric command ID. Extracted by tracing register values through the constructor calls. **Important**: Kotlin enum ordinals and explicit `cmd` IDs are different numbers. The `cmd` value is what goes on the wire. #### 3. Module IDs (`WsModuleId.smali`) The `WsModuleId` enum uses **ordinal values only** (no custom id field). Module ID = ordinal position in the enum (0-18). #### 4. BLE Packet Format (`l80.smali`) The `l80` class (obfuscated name for `BluetoothPacket`) encodes packets in method `j()`: - Magic byte `0xAA` at position 0 - 9-byte header: protocolVersion, cmdInstruction, packageSequence, totalPackages, extendedProtocol (2B), validDataLength (2B) - Payload: protobuf data - CRC-16 computed by class `vc0` over header+payload - End marker `0x0D` The CRC lookup table in `vc0.smali` starts with `{0x0000, 0xC0C1, 0xC181, 0x0140, ...}` which identifies it as CRC-16/MODBUS (reflected polynomial 0xA001 = 0x8005 reflected, init 0xFFFF). #### 5. WebSocket URL (`v55.smali`) The URL is assembled by concatenating: `"ws://"` + `yd3.b()` (host IP) + `":9900/?client_id="` + `y32.c()` (client ID). Two additional constants: `0x1139` (4409) and `0x113A` (4410) for secondary ports. #### 6. DeviceType IDs (`DeviceType.smali`) The constructor signature is `(String name, int ordinal, int deviceId, int nameResId)`. The `deviceId` parameter is the on-wire device identifier. Careful register tracing is required because smali reuses registers: - Unknown: deviceId=0 - DWARF_2: deviceId=1 - DWARF_3: deviceId=2 - DWARF_mini: deviceId=4 (ordinal=3, **gap at deviceId=3**) - DWARF_4: deviceId=5 - DWARF_DRAGON: deviceId=6 #### 7. Proto Message Fields (`smali_classes5/com/convergence/dwarflab/proto/`) Each `.smali` file in the proto package corresponds to a protobuf message. Field numbers are embedded as constants in the `writeTo()` method (serialized using `writeString(fieldNumber, value)`, `writeInt32(fieldNumber, value)`, etc.). Field names are preserved in the obfuscated class names via Kotlin metadata annotations. ### Limitations - **Obfuscated names**: Most class names are obfuscated (e.g., `l80`, `cg1`, `j80`). Kotlin metadata annotations help recover some names. - **No `.proto` files**: The original `.proto` source files are not included in the APK. Field names and numbers are inferred from the generated Java/Kotlin code. - **String literals**: Some strings (UUIDs, URLs, keys) are embedded directly and can be extracted with certainty. Others require contextual inference. - **Behavioral details**: Timing, retry logic, and UI flow are inferred from the code but not directly observable without a device. - **Version-specific**: This documentation corresponds to APK v3.4.0. Newer or older versions may differ. ### Verification All data points were cross-validated in two passes: 1. **First pass**: Initial extraction from smali source code 2. **Second pass**: Independent re-reading of each smali file to confirm register values, field numbers, and constants Key verifications: - All 8 BLE UUIDs confirmed from `cg1.smali` - All 19 module IDs confirmed from `WsModuleId.smali` (ordinals) - All ~300 WsCmd command IDs confirmed from `WsCmd.smali` (hex → decimal conversions) - All 8 WsPacket field numbers confirmed from `BaseProto$WsPacket.smali` - DeviceType IDs confirmed with register tracing (including the gap at deviceId=3) - BLE command bytes (0-7) confirmed from `j80.smali` - BLE packet format confirmed from `l80.smali` (header layout, CRC, end marker) - WebSocket URL and ports confirmed from `v55.smali` - CRC-16/MODBUS confirmed from `vc0.smali` lookup table