Haven Docs

Accessibility service

Haven uses an AccessibilityService. That is a powerful API, so this page is precise about what it is used for, what it reads, what it ignores, and what happens to what it reads.

Why an accessibility service is necessary#

Three of Haven's four protection layers cannot be built any other way on Android:

LayerWhat it needsWhy nothing else works
Gambling-app blockTo know which app came to the foregroundThere is no other API that reports the foreground app in real time without usage-stats access, which is broader and retrospective
Financial protectionThe same signal, for user-chosen money appsAs above
Blocked-site redirectThe address bar of a known browserA DNS block produces a cold browser error page; there is no way to replace it from outside the browser
Page-content watchThe visible text and structure of a browser pageThe alternative — inspecting network traffic — would require breaking TLS, which Haven will not do

That last row is the important one. The accessibility route reads what is already on the user's own screen, on the user's own device. The alternative would be intercepting encrypted traffic. Haven considers the accessibility route strictly less invasive, and it is an architectural rule of the project that TLS is never touched.

What the service is configured to receive#

xml
<accessibility-service
    android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault|flagReportViewIds"
    android:canRetrieveWindowContent="true"
    android:description="@string/financial_accessibility_description"
    android:notificationTimeout="50" />
  • Window-state changes tell Haven which app is in the foreground.
  • Window-content changes, together with content retrieval, let Haven read the address bar and the visible page text — in known browser packages only, checked in code.
  • No gesture dispatch, no global actions to manipulate other apps, no key-event filtering, no touch exploration.

What is read, and what is ignored#

ReadScope
The foreground package nameEvery app
That package's display labelOnce per unseen package, from the device's own package manager
The address bar textKnown browsers only
The visible page text and structureKnown browsers only, and only when the domain rules neither block nor allow the host
Ignored entirely
The window content of every non-browser app
Banking, payment and crypto apps — only the fact that one is in the foreground is used
Messaging apps, email, notes, photos, health apps, everything else
Passwords and form fields — Haven never harvests input fields

The address bar is a special case: it is kept in the tree so page structure is measured correctly, but its text is stripped before scoring. It contains user input or someone else's link, and treating it as page content would let a link get any domain permanently blocked. See Detection layers.

What happens to what is read#

This is the part that matters most:

  • Page text is inspected in memory and discarded. It is never written to storage and never transmitted anywhere.
  • Address-bar text is never stored. It is compared against the on-device rules and dropped.
  • Nothing read through this service is sent off the device. Ever.
  • The only thing that outlives a scan is a matched domain name, which is written to the local block log and, for a confirmed catch, to the user's own filters — where they can see it and remove it.

Every decision is made by pure, on-device code. No screen content is uploaded for classification.

The user-facing description#

Android shows this text in the accessibility settings screen, in the app's chosen language:

Gives you a calm pause when you open a bank, payment or crypto app that you picked. In your browser, it replaces the error page of a blocked site with a calm moment instead. It only reads which app is open and — only in known browsers — the web address and the text you can see on the page, so it can spot blocked sites it does not know yet. Page text is never saved and never sent anywhere. Only a matched website name goes into your own filters and log, on this phone.

  • The user grants this explicitly, in Android's own settings. Haven cannot grant it itself and does not try.
  • It can be revoked at any time from the same screen. Haven does not attempt to detect, discourage or prevent revocation.
  • Haven checks whether the service is actually running and says so in the interface. A protection app that looks on while it is silently inert is worse than one that is honestly off — so the App-check screen will name the missing switch rather than promise that a flagged app "stays closed".
  • Android silently revokes the permission on every app update. Haven therefore re-offers it after an update rather than treating an old "not now" as permanent.

Performance discipline#

Because the event callback is hot, it is written to stay cheap: the settings it needs are observed reactively and cached in memory rather than read from storage, the cheap checks (is this a browser, is protection on) run first, per-package verdicts are memoised against the rule-set version, and a page scan walks the accessibility tree exactly once under a hard node budget.

Compliance summary#

Google Play accessibility requirementHaven
The service must be used for accessibility-adjacent functionality that benefits the userIt blocks gambling content and adds a reflection pause for a user who asked for both
Prominent disclosure of what it doesShown before the permission is requested, and in the system description above
No collection of personal or sensitive data through the servicePage text is discarded; nothing read is transmitted
No use for advertising, analytics or profilingNo analytics or advertising SDK exists in the app
The user must be able to disable itFrom Android settings at any time, without interference

See Sensitive permission declarations.