3.6 KiB
Device Profile Generation Design
Goal
Build a self-contained device identity generation pipeline for producing many stable, self-consistent Android device profiles without depending on live APP runtime state.
The first deliverable is local identity generation and persistence. Online DFP
bootstrap is intentionally separated into a later step because egid and cloud
did are server-issued values and require a coherent deviceInfo payload.
Current Findings
Known runtime relationships:
oDid = "ANDROID_" + android_idrdid = "ANDROID_" + md5(gRdi2)[16:32]- local fallback
didcan be generated independently - cloud
didandcdid_tagoverride local fallback values after unifiedId refresh egidis returned by DFP report, not derived by a local hash
Observed sample:
android_id=46a032e0a2af8184
oDid=ANDROID_46a032e0a2af8184
gRdi2=799999139::8641|899999556::8641|999999345::4741|899999995::8641|999999515::4741
md5(gRdi2)=be49e5841412c571741de4351c44850d
rdid=ANDROID_741de4351c44850d
did=ANDROID_e8dfd2f16b618053
cdid_tag=2
Scope
Included in phase 1
- Generate local Android identity fields.
- Generate a stable
gRdi2string and matchingrdid. - Generate a local fallback
did. - Persist and reload profiles without changing identities.
- Apply server identity values later through an explicit update method.
- Export profiles as JSON and
.envsnippets for other scripts.
Excluded from phase 1
- Calling DFP/unifiedId services.
- Producing a guaranteed valid
egid. - Replacing
main.pytask runner behavior. - Reusing HAR files as runtime templates.
Architecture
core/device_profile.py
Owns device identity data and local generation rules.
Main objects:
DeviceProfile: serializable profile model.DeviceProfileGenerator: creates new profiles from a random source.load_device_profile(path): loads a persisted profile.save_device_profile(profile, path): writes profile JSON.
tools/new_device.py
Small CLI wrapper around the core generator.
Responsibilities:
- create one or more profiles
- save JSON files
- optionally print
.envformat - avoid depending on APP, Frida, HAR, or
out/
Tests
tests/test_device_profile.py verifies:
- android_id is 16 lowercase hex characters
oDidmatches android_idrdidmatchesmd5(gRdi2)[16:32]- persisted profile reloads identically
- cloud identity update changes
did,cdid_tag, andegidonly when explicit
Data Flow
new_device.py
-> DeviceProfileGenerator.new_profile()
-> DeviceProfile.to_dict()
-> save JSON / print env
existing JSON
-> load_device_profile()
-> use stable identity in request builders
server response
-> profile.apply_cloud_identity(did, cdid_tag, egid)
-> save JSON
Error Handling
- Invalid
android_id,did,oDid,rdid, oregidvalues raiseValueError. - Loading malformed JSON raises
ValueErrorwith the file path. - Existing output files are not overwritten unless the CLI receives
--force. - Batch generation creates separate files and fails fast on duplicate filenames.
Testing Strategy
Use TDD:
- Write failing tests for local generation and persistence.
- Implement minimal core code to pass tests.
- Add CLI tests or smoke checks.
- Run focused tests and compile checks before claiming completion.
Future Phase
After phase 1, add an online bootstrap layer:
DeviceProfile
-> build DFP fetch/check/repair/report forms
-> call unifiedId / gdfp report
-> apply cloud did / cdid_tag / egid
That layer should migrate useful code out of out/build_dfp_*.py into core/
without making main.py depend on HAR templates.