App 2.19.5: the installer screen fallback reads the APK
The car refuses the silent session for a non-system app; the fallback installer screen could not read our FileProvider URI because grants from the system user are refused. The car build now hands it a file URI to the verified copy in Downloads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
@@ -71,7 +71,9 @@ version, checks it against the `.sha256`, checks the package, and installs it wi
|
|||||||
installer session as an over-the-air update. The car build only; the stable build has no button.
|
installer session as an over-the-air update. The car build only; the stable build has no button.
|
||||||
|
|
||||||
On the Android 9 emulator (car build, system user) this installed without asking, from the
|
On the Android 9 emulator (car build, system user) this installed without asking, from the
|
||||||
storage's top folder; on the car the stick's top folder is used the same way.
|
storage's top folder; on the car the stick's top folder is used the same way, and the install
|
||||||
|
ends on Android's installer screen, confirmed with **Install** (below). Every step, with the
|
||||||
|
platform's own words, is on the Logs tab under "Updates".
|
||||||
|
|
||||||
## When it says something else
|
## When it says something else
|
||||||
|
|
||||||
@@ -100,5 +102,11 @@ path: the app opens the archive itself and streams it in. The approach comes fro
|
|||||||
the same wall on the same hardware. Upstream later fell back to "download to Downloads and
|
the same wall on the same hardware. Upstream later fell back to "download to Downloads and
|
||||||
tap it"; this fork tries the session first and keeps that as the fallback.
|
tap it"; this fork tries the session first and keeps that as the fallback.
|
||||||
|
|
||||||
**Not yet tried on this car:** whether the session installs silently as the system user, or
|
**On the car (SWI68, 2026-10-23) the session is refused:** the package manager answers
|
||||||
asks for a confirmation.
|
`Not allowed to install non-system apps on internal storage` — a firmware policy for apps that
|
||||||
|
are not system apps, even when they run as the system user. The app then opens Android's own
|
||||||
|
installer screen, where the driver confirms with **Install**, the same route the Files app takes.
|
||||||
|
That screen needs a `file://` URI on the car build: a read grant on our FileProvider is refused
|
||||||
|
when it comes from the system user (`not exported from UID 1000`), and the installer reports the
|
||||||
|
unreadable file as "There was a problem parsing the package". On the emulator the session still
|
||||||
|
installs silently.
|
||||||
|
|||||||
@@ -118,6 +118,14 @@ tyre pressures, GPS (lat, lon, elevation, heading) and the is_* flags. It does *
|
|||||||
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
||||||
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
||||||
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
||||||
|
- 2026-10-23 — App 2.19.5: installing from USB (and over the air) works on the car again, with a
|
||||||
|
confirmation. The update log showed the car refusing the silent session: `Not allowed to install
|
||||||
|
non-system apps on internal storage`. The fallback, Android's installer screen, then said "There
|
||||||
|
was a problem parsing the package": as the system user, our FileProvider's read grant to the
|
||||||
|
installer is refused (`not exported from UID 1000`). The car build now hands the installer a
|
||||||
|
file URI to the verified copy in Downloads (StrictMode's file-URI check lifted for that one
|
||||||
|
call). On the emulator, with the session forced to fail as on the car, the installer screen
|
||||||
|
asked to update and installed it. Not tried on the car yet. OTA.md updated.
|
||||||
- 2026-10-23 — App 2.19.4: "Export CarPlay data" on the Logs tab (Foreground apps card), for the
|
- 2026-10-23 — App 2.19.4: "Export CarPlay data" on the Logs tab (Foreground apps card), for the
|
||||||
question whether CarPlay's resolution can change. CarPlay with policy_control still leaves a grey
|
question whether CarPlay's resolution can change. CarPlay with policy_control still leaves a grey
|
||||||
strip, also after reconnecting: Allgo announces a smaller picture to the iPhone. 20 s after the
|
strip, also after reconnecting: Allgo announces a smaller picture to the iPhone. 20 s after the
|
||||||
|
|||||||
+2
-2
@@ -34,8 +34,8 @@ android {
|
|||||||
applicationId "com.stinnesbeck.nilsmg4"
|
applicationId "com.stinnesbeck.nilsmg4"
|
||||||
minSdk 27
|
minSdk 27
|
||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode 103
|
versionCode 104
|
||||||
versionName "2.19.4"
|
versionName "2.19.5"
|
||||||
|
|
||||||
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
||||||
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
||||||
|
|||||||
@@ -566,6 +566,28 @@ final class OtaUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File publicApk = copyToPublicDownloads(apk);
|
File publicApk = copyToPublicDownloads(apk);
|
||||||
|
if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
|
||||||
|
// As the system user, our FileProvider's read grant is refused ("not exported from
|
||||||
|
// UID 1000") and the installer reports the unreadable file as a parse error. A file
|
||||||
|
// URI it reads with its own storage permission instead, as from the Files app.
|
||||||
|
Intent install = new Intent(Intent.ACTION_VIEW)
|
||||||
|
.setDataAndType(Uri.fromFile(publicApk), "application/vnd.android.package-archive")
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (install.resolveActivity(context.getPackageManager()) == null) {
|
||||||
|
throw new IllegalStateException("No package installer activity");
|
||||||
|
}
|
||||||
|
// StrictMode forbids file URIs in intents (FileUriExposedException): lifted for this
|
||||||
|
// one call only.
|
||||||
|
android.os.StrictMode.VmPolicy policy = android.os.StrictMode.getVmPolicy();
|
||||||
|
android.os.StrictMode.setVmPolicy(new android.os.StrictMode.VmPolicy.Builder().build());
|
||||||
|
try {
|
||||||
|
context.startActivity(install);
|
||||||
|
} finally {
|
||||||
|
android.os.StrictMode.setVmPolicy(policy);
|
||||||
|
}
|
||||||
|
Log.i(TAG, "System install UI opened with a file URI for " + publicApk.getAbsolutePath());
|
||||||
|
return;
|
||||||
|
}
|
||||||
Uri contentUri = FileProvider.getUriForFile(context,
|
Uri contentUri = FileProvider.getUriForFile(context,
|
||||||
context.getPackageName() + ".fileprovider", publicApk);
|
context.getPackageName() + ".fileprovider", publicApk);
|
||||||
Intent install = new Intent(Intent.ACTION_VIEW)
|
Intent install = new Intent(Intent.ACTION_VIEW)
|
||||||
|
|||||||
Reference in New Issue
Block a user