# [DЯΣΛMMΛKΣЯ] ## . //0VΣЯW4TCH A native Android (Kotlin) **passive surveillance-detection** app. Open it, hit **START**, and a circle turns **green / yellow / orange / red** depending on how confident the engine is that there's a Flock Safety ALPR, an Axon body camera, or active police presence near you. With the screen locked, the foreground notification updates with the current tier and the phone vibrates on upward escalations — you don't have to be looking at the screen. > **Passive defense only.** OVERWATCH only listens — it does not transmit, > probe, jam, or interfere with any device or network. The Axon > advertise/fuzz code from one of the reference projects is intentionally > excluded. Website: **[overwatch.netslum.io](https://overwatch.netslum.io)** · Latest release: [v0.5.3](https://github.com/KaraZajac/OVERWATCH/releases) (debug-signed APK, sideload). --- ## Screenshots
Live threat-map circle · source drill-down · settings
--- ## What it detects | Source | What it looks at | Where it comes from | |---|---|---| | **BLE** | Bluetooth-LE advertisements: vendor MAC OUIs (Axon, Flock Penguin / Raven, XUNTONG mfg id `0x09C8`, "TN" serial pattern), Raven service UUIDs, device-name patterns | Local radio scan (BLE callback API). Iterates every manufacturer-specific data entry to find XUNTONG, not just the first. | | **WiFi** | BSSID OUI prefixes for Flock infrastructure (31-prefix superset), `Flock-XXXX` and other generic SSID patterns | `WifiManager.getScanResults()` polled every 35 s (just under the Android 11+ 4-scans/2-min throttle) | | **DEFLOCK** | Crowdsourced ALPR locations within configurable proximity (default 200 m) | POST to Overpass API (`overpass.deflock.org` → fallback `overpass-api.de`) for `man_made=surveillance + surveillance:type=ALPR` in a 5 km bbox; 24 h on-disk cache by 0.05° grid cell. Refetches when the user moves > 1.5 km from the last fetch center. Backoffs after Overpass failures; treats `{"remark": "...timed out..."}` 200-responses as failure so timeouts don't poison the cache. | | **CITIZEN** | Real-time public-safety incidents (police-relevant only — fire/medical-only events filtered out) within configurable proximity, < 30 min old | `citizen.com/api/incident/trending` (bbox) polled every 60 s, then per-incident detail via `/api/incident/{id}` with an in-memory cache so each incident is fetched once per session. First poll fires immediately on the first location fix. | | **WAZE** | User-reported `POLICE` alerts still active in the feed within configurable proximity (default 500 m), up to ~45 min old | `api.blackflagintel.com/waze/alerts-and-jams` — the OVERWATCH proxy (Caddy) that injects the OpenWeb Ninja key server-side and forwards to their hosted Waze scrape, sidestepping the reCAPTCHA gating that 403s direct `live-map/api/georss` calls. The app authenticates with an `X-App-Token` entered in Settings (encrypted on-device); the paid key never ships in the APK. Polled every ~4 min. Upstream ignores type filtering and caps at 200 alerts, so the client pulls the full page and filters to `POLICE` itself. Alerts carry confidence (0–5) + reliability (0–10); high values nudge the score up. No token → source shows "not configured" in the drill-down. | | **COMMERCIAL** | Nearby consumer smart-home / voice gear (Nest, Ring, Echo, hidden cams) and camera-bearing smart glasses (Meta, Snap, Vuzix) as a secondary situational signal | Rides the BLE + WiFi scans — OUI / device-name / service-UUID / SSID matches plus Bluetooth SIG company IDs from `MicTargets`. Score-capped at ORANGE so a cluster of doorbells (or a passing pair of Ray-Bans) never reads as ALPR-grade certainty. | > **Waze is back (v0.4.0+), via a key-protected proxy.** Waze reCAPTCHA-gated its `live-map/api/georss` endpoint in 2025/2026 — automated calls get HTTP 403 regardless of IP or headless-vs-headful browser (it scores browser *reputation*, verified by direct testing), which is why v0.1.5 removed the original integration and why no free scraper survives. OVERWATCH reads Waze POLICE alerts through [OpenWeb Ninja](https://www.openwebninja.com)'s hosted feed (pay-as-you-go ~$0.005/req, ≈ $1–3/mo at the 4-min poll). To keep the paid key off every device, the app doesn't hold it: a Caddy reverse proxy at `api.blackflagintel.com` injects the key server-side, and the app authenticates with a scoped, revocable `X-App-Token` entered in Settings (stored encrypted via the Android Keystore). The Waze for Cities partner feed was ruled out — it excludes POLICE and is agency-only. Waze complements Citizen: denser for roadway stops / speed traps. Every observation is scored 0–100 by `ConfidenceEngine`. The on-screen tier is the maximum live score across all sources: ``` GREEN < 40 nothing credible YELLOW 40 – 69 single weak indicator ORANGE 70 – 84 high confidence RED 85 + certain ``` The user-facing circle uses the full 4-tier mapping. Cross-source corroboration naturally pushes the global max upward (a BLE OUI hit *and* a DeFlock map match in the same area produce a higher tier than either alone). When idle, the circle shows muted gray with `IDLE` text so it's distinguishable at a glance from "scanning, all clear." While scanning, the circle becomes a live OpenStreetMap centered on you, wrapped in a **threat-color ring** (the current tier at a glance) and marked with a ⌖ crosshair for your position. Map geodata is color-coded by source — **Flock / DeFlock cameras red, Waze police blue, Citizen incidents purple** — so each dot is self-explanatory. The same map renders in a smaller floating overlay bubble (Settings → Display over other apps) so it works over other apps. --- ## How alerts work - **In-app**: the threat circle shows a live map with a threat-color ring and source-color dots while scanning; tap it to open the bottom-sheet drill-down with per-source rows. DeFlock, Citizen, and Waze events carry coordinates — each row has a tap-to-open Maps icon. - **Foreground notification**: rebuilt on every threat-tier change. Title becomes `OVERWATCH • RED` (or whatever tier); text shows the top detection's score + label. Notification priority bumps to HIGH on RED so the system can surface it as a heads-up. - **Vibration**: on upward tier transitions only. Short pulse for YELLOW, double for ORANGE, escalating triple for RED. Toggle in Settings → Alerts. - **Per-source health**: the drill-down sheet shows orange `Source unreachable` text on a row when its scanner couldn't reach its data source — silent empty results vs. real failures are distinguishable. --- ## Architecture ``` ui/MainScreen.kt map circle + threat ring + START/STOP + drill-down sheet ui/OverlayBubble.kt floating "chat-bubble" version of the map circle ui/MarkerIcons.kt map marker drawables — source dots + ⌖ user crosshair ui/SettingsScreen.kt source toggles, distance sliders, Waze token, vibrate, theme ui/theme/Theme.kt Material 3 dark/light + threat colors service/DetectionService.kt foreground service — owns scanners, notification, vibration service/OverlayManager.kt WindowManager host for the floating overlay bubble scan/BleScanner.kt BLE callback scanner scan/WifiScanner.kt WifiManager poller + SCAN_RESULTS receiver scan/DeflockClient.kt Overpass POST (deflock.org → overpass-api.de) + 24h cache scan/DeflockScanner.kt location-driven proximity check + failure backoff scan/CitizenClient.kt GET /api/incident/trending + /api/incident/{id} scan/CitizenScanner.kt 60 s poller, fire/medical filter, per-id cache scan/WazeClient.kt GET api.blackflagintel.com proxy (X-App-Token) → OpenWeb Ninja scan/WazeScanner.kt ~4 min poller, 200-alert page, client-side POLICE filter fusion/ConfidenceEngine.kt scoring (BLE / WiFi / DeFlock / Citizen / Waze / Commercial) fusion/RssiTracker.kt rise-peak-fall stationary-signal detector fusion/DetectionStore.kt in-memory dedup, 5-min retention, max-tier flow fusion/SourceHealth.kt per-source OK/FAILED registry for the drill-down fusion/ThreatLevel.kt 4-tier enum + DetectionSource enum data/location/LocationProvider.kt FusedLocationProviderClient wrapper data/settings/Settings.kt SharedPreferences-backed StateFlow settings data/settings/SecureStore.kt Keystore AES/GCM store for the Waze proxy token data/targets/ BleOuis, WifiOuis, RavenUuids, Patterns, Manufacturers, MicTargets ``` No detection-history database. All state is in-memory and clears on stop, by design. Service uses `START_NOT_STICKY` — system kill doesn't auto-restart into a stuck state. --- ## Build & install Requires: - **JDK 17** (17 or 21; Android Gradle Plugin 8.7.x rejects JDK 26) - **Android Studio** with SDK Platform 35 + Build-Tools 35.x + Platform-Tools ```sh # 1) Copy the example local.properties and point sdk.dir at your install cp local.properties.example local.properties # edit local.properties → sdk.dir=/Users/