Package visibility
Two permissions concern other apps on the device. Both are used narrowly, and neither results in anything leaving the phone.
QUERY_ALL_PACKAGES#
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent>
</queries>Where it is used#
| Use | Detail |
|---|---|
| App-check | Scans the apps that have a launcher entry and classifies each one, so the user can see which gambling apps are on their phone |
| Financial protection picker | Shows the user's installed apps so they can tick their own bank or payment apps instead of typing package names |
| Foreground app label | Reads the display name of an app the first time it is seen, as a second detection signal alongside its package name |
| Returning to a guarded app | Re-launching the one app the user chose to continue to, after the financial pause |
Why a narrower declaration will not do#
The launcher-intent <queries> element above is declared and covers the visible-app listing. It is not sufficient on its own for the classification path, which needs to resolve the label of whatever app comes to the foreground.
The alternative — enumerating specific packages in <queries> — fails for the reason the whole product is built around: it would mean listing every gambling operator's package name in the manifest. That list would be stale the week it shipped, could only be updated by publishing a new app version, and would break the core promise that a newly-listed operator is recognised without an app update.
What Haven does with the list#
- Reads it on-device only.
- Uses it to build a picker and to classify apps against the same rules the DNS layer uses.
- Stores nothing about installed apps off-device.
- Transmits nothing about installed apps anywhere — not to Haven's backend, not to any third party, not in any analytics payload (there is no analytics SDK).
- Does not write the scan result to any log that leaves the phone.
The scan result lives on screen and in local preferences (only the packages the user released as false positives are remembered).
REQUEST_DELETE_PACKAGES#
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />Used in exactly two places — the App-check screen and the wall shown when a detected gambling app is opened — and in both it does the same thing:
Intent(Intent.ACTION_DELETE, Uri.parse("package:$pkg"))This opens Android's own uninstall confirmation dialog.
Three things follow, and all three matter:
- Haven never uninstalls anything. It cannot. This permission only lets it ask the system to show the standard confirmation.
- The final tap is always the user's, in the system dialog, where the app being removed is named.
- The user can cancel, and nothing happens.
Haven never removes anything silently, never removes anything in the background, and never removes an app the user did not choose to remove.
A small implementation note#
While the system uninstall dialog is up, the app being removed briefly re-appears underneath it. Without care the gambling-app block would fire its own wall over the dialog and torpedo the very removal it just suggested, so Haven records that an uninstall was requested and holds off for that package. That record is in-memory only — after a restart, a still-installed gambling app is simply blocked again as normal.
Summary#
| Reads | Stores | Sends | |
|---|---|---|---|
| Installed app list | On-device, to classify and to build pickers | Only released false positives, locally | Nothing |
| App labels | On-device, first sighting of a package | Nothing | Nothing |
| Uninstall | Nothing — only opens the system dialog | Nothing persistent | Nothing |