Public Access
The foreground service existed, and four defects in its wiring meant it mostly did not run. A shell opening was never announced to it — only the ending was — so the service never came up for a shell at all. An idle connected Files session counted as nothing. Every refresh restarted the service, which Android 12+ answers with a crash the moment the app is backgrounded — a transfer finishing in the pocket took the remaining connections with it. And POST_NOTIFICATIONS was declared but never requested, so on Android 13+ the receipt was silently invisible. Updates while backgrounded now go through the notification manager; a foregrounded refresh still prefers a real start, so a stop still in flight cannot leave an orphan receipt over an unprotected process.
73 lines
4.2 KiB
XML
73 lines
4.2 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
|
|
<!-- SSH itself, the sync client, and the loopback socket the terminal renderer attaches to. -->
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
|
|
<!--
|
|
The foreground service that keeps shells and transfers alive across backgrounding — the decision
|
|
recorded in docs/android-port.md. dataSync is the type that matches what it actually does; Android 14
|
|
(API 34) rejects a service that starts without one declared here and on the <service> element.
|
|
-->
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
|
|
|
<!--
|
|
The service's persistent notification. Requested on API 33+ from SessionForegroundService.Reconcile,
|
|
the first time in this process there is actually something to show — not at launch, where the ask
|
|
would justify nothing on screen yet. Refusal is survivable: the service still starts and still holds
|
|
the process in the foreground either way, so a "no" costs the notification and nothing else.
|
|
-->
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
|
|
<!-- Releases the device key. See AndroidDeviceKeyStore. -->
|
|
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
|
|
|
<!--
|
|
◆ Hands a downloaded APK to the system installer, which is the whole of this head's updater. See
|
|
AndroidUpdateChannel and ADR 0014.
|
|
|
|
It is worth being exact about what this permission is and is not. It does not let this application
|
|
install anything: it lets it *ask*, and the platform then shows its own confirmation naming the
|
|
package and the source. On API 26 and later it is additionally gated by a per-application setting the
|
|
user has to turn on in Settings, which no permission dialogue can grant — so the first update walks
|
|
them there. Nothing is installed without two deliberate answers, neither of them to a screen this
|
|
application drew.
|
|
|
|
Declared rather than avoided by opening the release page in a browser. That would work, and it would
|
|
move the same install through Chrome's downloads and the same unknown-sources gate with one more step
|
|
and no less trust. What it would also do is give up any way of knowing a fix has been fetched, which
|
|
for an SSH client holding a team's credentials is the property ADR 0011's consequences call the
|
|
sharpest edge of shipping outside a store.
|
|
-->
|
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
|
|
|
<!--
|
|
allowBackup and fullBackupContent are both off deliberately, and both are vault properties rather
|
|
than defaults worth inheriting. The local cache is a SQLite file holding the ciphertext mirror, the
|
|
outbox and the offline unlock material; letting Android back it up would copy vault material into a
|
|
Google-held backup that this product's threat model says nothing about. It would also restore one
|
|
phone's outbox onto another, which is the same corruption ClientPaths already refuses by insisting on
|
|
a local, non-roaming directory.
|
|
-->
|
|
<!--
|
|
The launcher icon is the same >_ box the sign-in and locked screens draw, as a vector
|
|
adaptive icon. See Resources/mipmap-anydpi-v26/ic_launcher.xml. No android:roundIcon:
|
|
that attribute exists so a launcher wanting a circle can be handed a second bitmap, and
|
|
an adaptive icon is already masked to whatever shape the launcher asks for.
|
|
-->
|
|
<!--
|
|
@string/app_name rather than the literal that was here, because the two channels are two installable
|
|
applications and both showing "DodoSSH" under the launcher icon is a home screen nobody can read. The
|
|
release channel's copy of that string is exactly what was written here before. See
|
|
Resources/values/strings.xml, and MainActivity, which has to name the same resource.
|
|
-->
|
|
<application android:label="@string/app_name"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:theme="@style/DodoTheme"
|
|
android:networkSecurityConfig="@xml/network_security_config"
|
|
android:allowBackup="false"
|
|
android:fullBackupContent="false" />
|
|
|
|
</manifest>
|