Skip to content

Commit 8209440

Browse files
committed
docs: update mobile architecture with implementation notes
1 parent f812620 commit 8209440

1 file changed

Lines changed: 91 additions & 5 deletions

File tree

DOSafe-Mobile-Architecture.md

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,99 @@ Requires user to set DOSafe as default phone app screening provider (RoleManager
263263

264264
CallDirectory Extension syncs DOSafe block list to iOS system. Updates via background fetch (max 24h). iOS does NOT support dynamic per-call screening — only static block list + caller ID label.
265265

266+
---
267+
268+
## Caller ID App DB Extraction Results
269+
270+
**Method:** Android emulator (Google APIs, root via `adb root`) + `-writable-system` flag.
271+
Extract offline spam databases from popular caller ID apps to seed DOSafe threat_intel.
272+
273+
| App | Package | Result | Records |
274+
|-----|---------|--------|---------|
275+
| **TrueCaller** | `com.truecaller` | **Offline DB readable**| **40k** top spammers VN (alias + report_count + categories) |
276+
| **nTrust** (NCA) | `com.nca.vn.ntrust` | **Offline DB readable**| **180k–252k** phone numbers (hotList: spam/fraud/whitelist) |
277+
| GetContact | `app.source.getcontact` | API-only, no offline spam DB | 0 |
278+
| Whoscall | `gogolook.callgogolook2` | Encrypted DB (SQLCipher) + requires Play Store | 0 |
279+
| Hiya || Requires Google Play Store | N/A |
280+
| TrustCall VN | `com.vn.trustcall` | Requires Google Play Store | N/A |
281+
| iCallMe || 26 demo records only | 26 |
282+
| CallApp || No offline spam DB | 0 |
283+
| Mr. Number || Paid subscription required | N/A |
284+
| Caller ID & Block || Crash on emulator | N/A |
285+
286+
### TrueCaller extraction
287+
- DB path: `/data/data/com.truecaller/databases/tc.db``topspammers` table
288+
- Fields: `value` (phone), `label` (display name), `count` (report count), `spam_categories`
289+
- Extracted via Google APIs emulator (adb root) with original unpatched APK
290+
- Patched APK FAILED: TrueCaller has server-side integrity check (signature verification)
291+
292+
### nTrust extraction
293+
- DB path: `/data/data/com.nca.vn.ntrust/databases/database.db``phone_number` table
294+
- Fields: `id`, `dial_id`, `name`, `contact_type` (hotList), `type_tag` (spam/fraud), `dial_code`, `part_id`
295+
- App is Flutter-based (NCA Vietnam), no Play Store requirement
296+
- Data refreshes on app launch — re-extract periodically for new numbers
297+
298+
### Key learnings
299+
- Google APIs image (root) + `-writable-system` required for DB extraction
300+
- API 34 recommended (API 36 dm-verity too strict)
301+
- Most modern caller ID apps either encrypt DB or require Play Store
302+
- `adb backup` returns empty (47 bytes) for apps with `allowBackup=false`
303+
- ARM translation works on API 34 x86_64 emulator — can install arm64 split APKs
304+
305+
---
306+
266307
### Flutter platform channel
267308

268309
```dart
269-
// lib/services/call_screening_channel.dart
270-
const _channel = MethodChannel('dosafe/call_screening');
310+
// lib/features/call_screening/data/call_screening_channel.dart
311+
const _channel = MethodChannel('io.dosafe/call_screening');
271312
272-
Future<void> setBlockList(List<String> numbers) async {
273-
await _channel.invokeMethod('setBlockList', {'numbers': numbers});
274-
}
313+
// Methods: hasRole, requestRole, openSettings, hasOverlayPermission,
314+
// requestOverlayPermission, writeIosIdentities
275315
```
316+
317+
---
318+
319+
## Implementation Status (2026-03-16)
320+
321+
### Completed
322+
- **Android CallScreeningService**`DosafeCallScreeningService.kt`, registered in manifest
323+
- **ROLE_CALL_SCREENING request** — system popup shows, user can select DOSafe
324+
- **Phone lookup** — calls DOSafe `/api/entity-check` for incoming numbers
325+
- **Blocklist sync**`/api/phone-blacklist` bulk endpoint, local SQLite cache
326+
- **Call screening UI** — enable/disable toggle, blocklist stats, sync button
327+
- **GitHub Actions CI/CD** — analyze + Android APK build (iOS pending signing)
328+
- **Repo**: `github.com/DOS/DOSafe-Mobile` (private)
329+
330+
### iOS Setup (pending Mac)
331+
- **CallerID** extension target created (Bundle ID: `me.dos.dosafe.callerid`)
332+
- **LiveCallerID** extension target created (Live Caller ID Lookup, iOS 18+)
333+
- Both use App Group `group.DOS.ID`
334+
- `CallDirectoryHandler.swift` code ready
335+
- Needs: `flutter pub get` on Mac → Cmd+B → commit `project.pbxproj`
336+
337+
### Critical Notes
338+
339+
**BIND_SCREENING_SERVICE permission:**
340+
```xml
341+
<!-- CORRECT — matches Truecaller -->
342+
android:permission="android.permission.BIND_SCREENING_SERVICE"
343+
344+
<!-- WRONG — will compile but role request auto-dismisses -->
345+
android:permission="android.permission.BIND_CALL_SCREENING_SERVICE"
346+
```
347+
Verified by dumping Truecaller manifest (`aapt2 dump xmltree`). The wrong permission name causes `RoleManager.createRequestRoleIntent()` to launch but immediately return `RESULT_CANCELED` (code=0) without showing the system picker dialog.
348+
349+
**FlutterFragmentActivity required:**
350+
Use `FlutterFragmentActivity` (not `FlutterActivity`) in `MainActivity.kt` to support `ActivityResultLauncher` for role requests on Android 12+.
351+
352+
**Bundle IDs:**
353+
- Android: `me.dos.dosafe` (namespace in build.gradle.kts)
354+
- iOS main: `me.dos.dosafe`
355+
- iOS CallerID: `me.dos.dosafe.callerid`
356+
- iOS LiveCallerID: `me.dos.dosafe.livecallerid`
357+
- Kotlin package: `io.dosafe.dosafe_mobile` (legacy, does not affect functionality)
358+
359+
**Signing:**
360+
- Android keystore: `android/app/dosafe-release.jks` (gitignored, base64 in GitHub Secrets)
361+
- iOS: pending provisioning profiles + certificates

0 commit comments

Comments
 (0)