Files
internet_use_control/android/app/build.gradle.kts
Sam Rolfe b534afb96d Phase 5.2: Android Usage Access telemetry + VpnService site filtering
Continue the Phase 5.1 kids' client (FR-7, FR-14, FR-18).

- Usage Access telemetry: UsageCollector reads the OS per-app foreground
  total for the day, TelemetryStore keeps the highest value per (day, app)
  across restarts, and TelemetryReporter samples every 60 s and publishes
  the list form on restrict/<device>/telemetry. Queued rows republish when
  the broker link returns.
- Device-local VpnService: SiteFilterVpnService routes only a fake resolver
  into its own tunnel, answers NXDOMAIN for a blocked host while locked,
  and forwards everything else upstream through a protected socket. The
  allowlist always wins (FR-4). No router, Pi-hole or DNS change.
- MQTT link: caFile support plus the telemetry topic and payload.
- Status screen: Usage Access, telemetry totals and site-filter state.
- Unit tests for host matching, DNS parse/NXDOMAIN and IPv4/UDP round trip.

No Device Owner, no factory reset, no managed profile. The VPN consent
dialog is manual; adb cannot grant it (recorded in android/README.md).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-13 20:25:19 +11:00

72 lines
2.3 KiB
Kotlin

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "au.audasmedia.webrestrict.kids"
compileSdk = 35
defaultConfig {
applicationId = "au.audasmedia.webrestrict.kids"
minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "0.1.0-phase5.2"
// The emulator default: a device config with the Settings app blocked.
// A real device receives the retained config over MQTT and overwrites
// this, but a broker-less device must still block (FR-14).
buildConfigField("String", "DEFAULT_DEVICE_TOPIC", "\"restrict/harry_phone_1/config\"")
buildConfigField("String", "DEFAULT_DEVICE_NAME", "\"Harry's phone\"")
buildConfigField("String", "DEFAULT_BROKER_HOST", "\"192.168.20.13\"")
buildConfigField("int", "DEFAULT_BROKER_PORT", "8883")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
debug {
// The headless emulator proof installs the debug build. Keep the
// application id identical to release so the adb commands that
// enable the Accessibility Service stay simple.
versionNameSuffix = "-debug"
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
buildConfig = true
viewBinding = false
}
packaging {
resources.excludes += setOf("META-INF/*.kotlin_module")
}
}
dependencies {
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.7.0")
// MQTT over TLS on the 8883 plane (AGENTS.md §10 rule 6). The Java client is
// pure JVM, so it also runs under the unit tests.
implementation("org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5")
// JSON is identical on Android and on the JVM, so Config parsing is unit
// tested without Robolectric.
implementation("com.google.code.gson:gson:2.11.0")
testImplementation("junit:junit:4.13.2")
}