From ea8032a8138e9d4fd6c067bde57968e915e9c49f Mon Sep 17 00:00:00 2001 From: TCFDONMEZ Date: Fri, 9 Oct 2026 17:31:08 +0300 Subject: [PATCH] chore --- .../cache/_events_79120_d0eaad9b80692b5d.json | 1 + .../cache/_events_79235_382896d082e25d69.json | 1 + .next/dev/build-manifest.json | 15 + .next/dev/cache/.rscinfo | 1 + .../cache/turbopack/v16.4.0-e273d5b2/CURRENT | 1 + .next/dev/fallback-build-manifest.json | 15 + .next/dev/lock | 1 + .next/dev/logs/next-development.log | 3 + .next/dev/package.json | 3 + .next/dev/prerender-manifest.json | 6 + .next/dev/routes-manifest.json | 1 + .next/dev/server/app-paths-manifest.json | 1 + .../interception-route-rewrite-manifest.js | 1 + .next/dev/server/middleware-build-manifest.js | 15 + .next/dev/server/middleware-manifest.json | 6 + .next/dev/server/next-font-manifest.js | 1 + .next/dev/server/next-font-manifest.json | 6 + .next/dev/server/pages-manifest.json | 1 + .next/dev/server/preview-props.json | 5 + .next/dev/server/server-reference-manifest.js | 1 + .../dev/server/server-reference-manifest.json | 5 + .../dev/static/development/_buildManifest.js | 8 + .../development/_clientMiddlewareManifest.js | 1 + .next/dev/static/development/_ssgManifest.js | 1 + .next/dev/types/routes.d.ts | 55 ++ AGENTS.md | 10 + app/build.gradle | 4 + app/src/main/AndroidManifest.xml | 14 +- .../main/java/com/evsuite/abrp/AbrpApi.java | 123 ---- .../com/evsuite/abrp/AbrpUploadService.java | 622 +---------------- .../java/com/evsuite/abrp/BootReceiver.java | 37 +- .../java/com/evsuite/abrp/ConfigImport.java | 119 ---- .../evsuite/abrp/ConsumptionCloudClient.java | 309 ++++++-- .../com/evsuite/abrp/ConsumptionTracker.java | 49 ++ .../com/evsuite/abrp/HeadUnitWeather.java | 239 ------- .../java/com/evsuite/abrp/MainActivity.java | 659 ++---------------- .../java/com/evsuite/abrp/SecurePrefs.java | 70 -- .../com/evsuite/abrp/TelemetryPayload.java | 197 ------ .../java/com/evsuite/abrp/UploadCadence.java | 66 -- .../java/com/evsuite/abrp/UploadSettings.java | 75 +- app/src/main/res/drawable/ic_tab_abrp.xml | 23 - .../main/res/layout-w1000dp/activity_main.xml | 1 - app/src/main/res/layout-w1000dp/pane_abrp.xml | 26 - app/src/main/res/layout/activity_main.xml | 1 - app/src/main/res/layout/pane_abrp.xml | 27 - docs/MG4_PLATFORM_INSTALL.md | 103 +++ 46 files changed, 699 insertions(+), 2230 deletions(-) create mode 100644 .next/cache/_events_79120_d0eaad9b80692b5d.json create mode 100644 .next/cache/_events_79235_382896d082e25d69.json create mode 100644 .next/dev/build-manifest.json create mode 100644 .next/dev/cache/.rscinfo create mode 100644 .next/dev/cache/turbopack/v16.4.0-e273d5b2/CURRENT create mode 100644 .next/dev/fallback-build-manifest.json create mode 100644 .next/dev/lock create mode 100644 .next/dev/logs/next-development.log create mode 100644 .next/dev/package.json create mode 100644 .next/dev/prerender-manifest.json create mode 100644 .next/dev/routes-manifest.json create mode 100644 .next/dev/server/app-paths-manifest.json create mode 100644 .next/dev/server/interception-route-rewrite-manifest.js create mode 100644 .next/dev/server/middleware-build-manifest.js create mode 100644 .next/dev/server/middleware-manifest.json create mode 100644 .next/dev/server/next-font-manifest.js create mode 100644 .next/dev/server/next-font-manifest.json create mode 100644 .next/dev/server/pages-manifest.json create mode 100644 .next/dev/server/preview-props.json create mode 100644 .next/dev/server/server-reference-manifest.js create mode 100644 .next/dev/server/server-reference-manifest.json create mode 100644 .next/dev/static/development/_buildManifest.js create mode 100644 .next/dev/static/development/_clientMiddlewareManifest.js create mode 100644 .next/dev/static/development/_ssgManifest.js create mode 100644 .next/dev/types/routes.d.ts delete mode 100644 app/src/main/java/com/evsuite/abrp/AbrpApi.java delete mode 100644 app/src/main/java/com/evsuite/abrp/ConfigImport.java delete mode 100644 app/src/main/java/com/evsuite/abrp/HeadUnitWeather.java delete mode 100644 app/src/main/java/com/evsuite/abrp/SecurePrefs.java delete mode 100644 app/src/main/java/com/evsuite/abrp/TelemetryPayload.java delete mode 100644 app/src/main/java/com/evsuite/abrp/UploadCadence.java delete mode 100644 app/src/main/res/drawable/ic_tab_abrp.xml delete mode 100644 app/src/main/res/layout-w1000dp/pane_abrp.xml delete mode 100644 app/src/main/res/layout/pane_abrp.xml create mode 100644 docs/MG4_PLATFORM_INSTALL.md diff --git a/.next/cache/_events_79120_d0eaad9b80692b5d.json b/.next/cache/_events_79120_d0eaad9b80692b5d.json new file mode 100644 index 0000000..a25504d --- /dev/null +++ b/.next/cache/_events_79120_d0eaad9b80692b5d.json @@ -0,0 +1 @@ +[{"eventName":"NEXT_CLI_SESSION_STOPPED","payload":{"nextVersion":"16.4.0","nodeVersion":"v24.12.0","cliCommand":"dev","durationMilliseconds":348,"turboFlag":true,"pagesDir":false,"appDir":true,"isRspack":false}}] \ No newline at end of file diff --git a/.next/cache/_events_79235_382896d082e25d69.json b/.next/cache/_events_79235_382896d082e25d69.json new file mode 100644 index 0000000..24ede18 --- /dev/null +++ b/.next/cache/_events_79235_382896d082e25d69.json @@ -0,0 +1 @@ +[{"eventName":"NEXT_CLI_SESSION_STOPPED","payload":{"nextVersion":"16.4.0","nodeVersion":"v24.12.0","cliCommand":"dev","durationMilliseconds":345,"turboFlag":true,"pagesDir":false,"appDir":true,"isRspack":false}}] \ No newline at end of file diff --git a/.next/dev/build-manifest.json b/.next/dev/build-manifest.json new file mode 100644 index 0000000..cc102f9 --- /dev/null +++ b/.next/dev/build-manifest.json @@ -0,0 +1,15 @@ +{ + "pages": { + "/_app": [] + }, + "devFiles": [], + "polyfillFiles": [], + "lowPriorityFiles": [ + "static/development/_buildManifest.js", + "static/development/_ssgManifest.js", + "static/development/_clientMiddlewareManifest.js" + ], + "rootMainFiles": [], + "rootMainFilesTree": {}, + "pagesChunkGroupBootstrapParams": {} +} \ No newline at end of file diff --git a/.next/dev/cache/.rscinfo b/.next/dev/cache/.rscinfo new file mode 100644 index 0000000..4830a4e --- /dev/null +++ b/.next/dev/cache/.rscinfo @@ -0,0 +1 @@ +{"encryption.key":"UT9PfJliySgklhhPCIM4wpEhmx9PMD9GPB4iuPIamyM=","encryption.expire_at":1792761221411} \ No newline at end of file diff --git a/.next/dev/cache/turbopack/v16.4.0-e273d5b2/CURRENT b/.next/dev/cache/turbopack/v16.4.0-e273d5b2/CURRENT new file mode 100644 index 0000000..5f9b019 --- /dev/null +++ b/.next/dev/cache/turbopack/v16.4.0-e273d5b2/CURRENT @@ -0,0 +1 @@ +{"max_sequence_number":0,"commit_time":"2026-10-09T13:13:41.418251Z"} diff --git a/.next/dev/fallback-build-manifest.json b/.next/dev/fallback-build-manifest.json new file mode 100644 index 0000000..cc102f9 --- /dev/null +++ b/.next/dev/fallback-build-manifest.json @@ -0,0 +1,15 @@ +{ + "pages": { + "/_app": [] + }, + "devFiles": [], + "polyfillFiles": [], + "lowPriorityFiles": [ + "static/development/_buildManifest.js", + "static/development/_ssgManifest.js", + "static/development/_clientMiddlewareManifest.js" + ], + "rootMainFiles": [], + "rootMainFilesTree": {}, + "pagesChunkGroupBootstrapParams": {} +} \ No newline at end of file diff --git a/.next/dev/lock b/.next/dev/lock new file mode 100644 index 0000000..faa33e6 --- /dev/null +++ b/.next/dev/lock @@ -0,0 +1 @@ +{"pid":79123,"port":3001,"hostname":"localhost","appUrl":"http://localhost:3001","startedAt":1791551621304} \ No newline at end of file diff --git a/.next/dev/logs/next-development.log b/.next/dev/logs/next-development.log new file mode 100644 index 0000000..2cc714a --- /dev/null +++ b/.next/dev/logs/next-development.log @@ -0,0 +1,3 @@ +{"timestamp":"00:00:01.802","source":"Server","level":"ERROR","message":"Turbopack build encountered 1 error:\n./app\nError: Could not find the Next.js package (next/package.json)\nResolved from: /Users/tcfdonmez/Desktop/Coding/MG/EVABRPUploader/app\nFilesystem root used for resolution: /Users/tcfdonmez/Desktop/Coding/MG/EVABRPUploader\n\nPossible causes:\n - node_modules is being reorganized by a concurrent install (e.g. pnpm adding a package with a `next` peer dependency). This is transient and should clear once the install completes.\n - node_modules/next was removed, renamed, or has a broken symlink.\n - The workspace root is incorrect — see turbopack.root in the Next.js config docs for how to configure it.\n - In a monorepo, the Next.js package may only exist in a directory above the closest directory containing a package manager lockfile. The workspace root is detected by locating the nearest package manager lockfile.\n - Next.js is installed globally rather than as a project dependency. This is not supported; install it locally.\n\nNote: To ensure a hermetic build and a portable cache, files outside of the workspace root are not compiled.\n\nhttps://nextjs.org/docs/app/api-reference/config/next-config-js/turbopack#root-directory\n\n"} +{"timestamp":"00:00:02.079","source":"Server","level":"LOG","message":""} +{"timestamp":"00:00:02.080","source":"Server","level":"LOG","message":"✓ Generated AGENTS.md for AI agents. Set `agentRules: false` in next.config to disable."} diff --git a/.next/dev/package.json b/.next/dev/package.json new file mode 100644 index 0000000..c9a4422 --- /dev/null +++ b/.next/dev/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} \ No newline at end of file diff --git a/.next/dev/prerender-manifest.json b/.next/dev/prerender-manifest.json new file mode 100644 index 0000000..4400a7a --- /dev/null +++ b/.next/dev/prerender-manifest.json @@ -0,0 +1,6 @@ +{ + "version": 4, + "routes": {}, + "dynamicRoutes": {}, + "notFoundRoutes": [] +} \ No newline at end of file diff --git a/.next/dev/routes-manifest.json b/.next/dev/routes-manifest.json new file mode 100644 index 0000000..442224a --- /dev/null +++ b/.next/dev/routes-manifest.json @@ -0,0 +1 @@ +{"version":3,"caseSensitive":false,"basePath":"","rewrites":{"beforeFiles":[],"afterFiles":[],"fallback":[]},"redirects":[{"source":"/:path+/","destination":"/:path+","permanent":true,"internal":true,"priority":true,"regex":"^(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))\\/$"}],"headers":[],"onMatchHeaders":[]} \ No newline at end of file diff --git a/.next/dev/server/app-paths-manifest.json b/.next/dev/server/app-paths-manifest.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.next/dev/server/app-paths-manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/.next/dev/server/interception-route-rewrite-manifest.js b/.next/dev/server/interception-route-rewrite-manifest.js new file mode 100644 index 0000000..24f77ba --- /dev/null +++ b/.next/dev/server/interception-route-rewrite-manifest.js @@ -0,0 +1 @@ +self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[]"; \ No newline at end of file diff --git a/.next/dev/server/middleware-build-manifest.js b/.next/dev/server/middleware-build-manifest.js new file mode 100644 index 0000000..4de4f4f --- /dev/null +++ b/.next/dev/server/middleware-build-manifest.js @@ -0,0 +1,15 @@ +globalThis.__BUILD_MANIFEST = { + "pages": { + "/_app": [] + }, + "devFiles": [], + "polyfillFiles": [], + "lowPriorityFiles": [ + "static/development/_buildManifest.js", + "static/development/_ssgManifest.js", + "static/development/_clientMiddlewareManifest.js" + ], + "rootMainFiles": [], + "rootMainFilesTree": {}, + "pagesChunkGroupBootstrapParams": {} +}; diff --git a/.next/dev/server/middleware-manifest.json b/.next/dev/server/middleware-manifest.json new file mode 100644 index 0000000..eb7130b --- /dev/null +++ b/.next/dev/server/middleware-manifest.json @@ -0,0 +1,6 @@ +{ + "version": 3, + "middleware": {}, + "sortedMiddleware": [], + "functions": {} +} \ No newline at end of file diff --git a/.next/dev/server/next-font-manifest.js b/.next/dev/server/next-font-manifest.js new file mode 100644 index 0000000..dcd0697 --- /dev/null +++ b/.next/dev/server/next-font-manifest.js @@ -0,0 +1 @@ +self.__NEXT_FONT_MANIFEST="{\n \"app\": {},\n \"appUsingSizeAdjust\": false,\n \"pages\": {},\n \"pagesUsingSizeAdjust\": false\n}" \ No newline at end of file diff --git a/.next/dev/server/next-font-manifest.json b/.next/dev/server/next-font-manifest.json new file mode 100644 index 0000000..7b7649c --- /dev/null +++ b/.next/dev/server/next-font-manifest.json @@ -0,0 +1,6 @@ +{ + "app": {}, + "appUsingSizeAdjust": false, + "pages": {}, + "pagesUsingSizeAdjust": false +} \ No newline at end of file diff --git a/.next/dev/server/pages-manifest.json b/.next/dev/server/pages-manifest.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.next/dev/server/pages-manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/.next/dev/server/preview-props.json b/.next/dev/server/preview-props.json new file mode 100644 index 0000000..0969aea --- /dev/null +++ b/.next/dev/server/preview-props.json @@ -0,0 +1,5 @@ +{ + "previewModeId": "a508c818777951bed52c0170453ef7e3", + "previewModeSigningKey": "591a19b72d1a845a81057e56fb15a2ced8409045c0ed580013f217b8c4a4ea61", + "previewModeEncryptionKey": "ded0359fbc3be263ec7ff240e7fb98fc5b836958070834f5bc954f1092afa91c" +} \ No newline at end of file diff --git a/.next/dev/server/server-reference-manifest.js b/.next/dev/server/server-reference-manifest.js new file mode 100644 index 0000000..272af9c --- /dev/null +++ b/.next/dev/server/server-reference-manifest.js @@ -0,0 +1 @@ +self.__RSC_SERVER_MANIFEST="{\n \"node\": {},\n \"edge\": {},\n \"encryptionKey\": \"UT9PfJliySgklhhPCIM4wpEhmx9PMD9GPB4iuPIamyM=\"\n}" \ No newline at end of file diff --git a/.next/dev/server/server-reference-manifest.json b/.next/dev/server/server-reference-manifest.json new file mode 100644 index 0000000..b5a989e --- /dev/null +++ b/.next/dev/server/server-reference-manifest.json @@ -0,0 +1,5 @@ +{ + "node": {}, + "edge": {}, + "encryptionKey": "UT9PfJliySgklhhPCIM4wpEhmx9PMD9GPB4iuPIamyM=" +} \ No newline at end of file diff --git a/.next/dev/static/development/_buildManifest.js b/.next/dev/static/development/_buildManifest.js new file mode 100644 index 0000000..bffda53 --- /dev/null +++ b/.next/dev/static/development/_buildManifest.js @@ -0,0 +1,8 @@ +self.__BUILD_MANIFEST = { + "__rewrites": { + "afterFiles": [], + "beforeFiles": [], + "fallback": [] + }, + "sortedPages": [] +};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB() \ No newline at end of file diff --git a/.next/dev/static/development/_clientMiddlewareManifest.js b/.next/dev/static/development/_clientMiddlewareManifest.js new file mode 100644 index 0000000..a8acaff --- /dev/null +++ b/.next/dev/static/development/_clientMiddlewareManifest.js @@ -0,0 +1 @@ +self.__MIDDLEWARE_MATCHERS = [];self.__MIDDLEWARE_MATCHERS_CB && self.__MIDDLEWARE_MATCHERS_CB() \ No newline at end of file diff --git a/.next/dev/static/development/_ssgManifest.js b/.next/dev/static/development/_ssgManifest.js new file mode 100644 index 0000000..2260768 --- /dev/null +++ b/.next/dev/static/development/_ssgManifest.js @@ -0,0 +1 @@ +self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() \ No newline at end of file diff --git a/.next/dev/types/routes.d.ts b/.next/dev/types/routes.d.ts new file mode 100644 index 0000000..15617e1 --- /dev/null +++ b/.next/dev/types/routes.d.ts @@ -0,0 +1,55 @@ +// This file is generated automatically by Next.js +// Do not edit this file manually + +type AppRoutes = never +type PageRoutes = never +type LayoutRoutes = never +type RedirectRoutes = never +type RewriteRoutes = never +type Routes = AppRoutes | PageRoutes | LayoutRoutes | RedirectRoutes | RewriteRoutes + + +interface ParamMap { +} + + +export type ParamsOf = ParamMap[Route] + +interface LayoutSlotMap { +} + + +export type { AppRoutes, PageRoutes, LayoutRoutes, RedirectRoutes, RewriteRoutes, ParamMap } + +declare global { + /** + * Props for Next.js App Router page components + * @example + * ```tsx + * export default function Page(props: PageProps<'/blog/[slug]'>) { + * const { slug } = await props.params + * return
Blog post: {slug}
+ * } + * ``` + */ + interface PageProps { + params: Promise + searchParams: Promise> + } + + /** + * Props for Next.js App Router layout components + * @example + * ```tsx + * export default function Layout(props: LayoutProps<'/dashboard'>) { + * return
{props.children}
+ * } + * ``` + */ + type LayoutProps = { + params: Promise + children: React.ReactNode + } & { + [K in LayoutSlotMap[LayoutRoute]]: React.ReactNode + } +} diff --git a/AGENTS.md b/AGENTS.md index 029daff..fe6a381 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -120,3 +120,13 @@ a stale Gradle daemon started by VS Code's Java extension is being reused — Most of this cannot be verified off a vehicle. When reporting work, state plainly what was tested and what was not. "Unit tests pass, not tried on the car" is the expected and acceptable answer. Do not imply road-testing that did not happen. + + + +## This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/app/build.gradle b/app/build.gradle index 79e31a5..8a597c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,6 +41,10 @@ android { // authenticated API in server/, which owns the database connection. buildConfigField "String", "CONSUMPTION_API_URL", "\"${System.getenv('CONSUMPTION_API_URL') ?: ''}\"" buildConfigField "String", "CONSUMPTION_API_TOKEN", "\"${System.getenv('CONSUMPTION_API_TOKEN') ?: ''}\"" + // Fixed installation identity: baked into every build so an APK wipe cannot orphan + // the cloud history under a new random UUID. The car's own consumption history lives + // under this id in the daily_consumption collection. + buildConfigField "String", "CONSUMPTION_INSTALLATION_ID", "\"226b1614-4d18-48f0-8938-3609cfa3db93\"" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 545d7f6..608eaba 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,9 +8,6 @@ - - - - - - - - + android:exported="false" /> - - - - diff --git a/app/src/main/res/layout-w1000dp/activity_main.xml b/app/src/main/res/layout-w1000dp/activity_main.xml index 8a3adb2..c1cae25 100644 --- a/app/src/main/res/layout-w1000dp/activity_main.xml +++ b/app/src/main/res/layout-w1000dp/activity_main.xml @@ -9,7 +9,6 @@ - diff --git a/app/src/main/res/layout-w1000dp/pane_abrp.xml b/app/src/main/res/layout-w1000dp/pane_abrp.xml deleted file mode 100644 index 8bd2c75..0000000 --- a/app/src/main/res/layout-w1000dp/pane_abrp.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b61ea7a..4a92f4f 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -16,7 +16,6 @@ - diff --git a/app/src/main/res/layout/pane_abrp.xml b/app/src/main/res/layout/pane_abrp.xml deleted file mode 100644 index 3f6065f..0000000 --- a/app/src/main/res/layout/pane_abrp.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/MG4_PLATFORM_INSTALL.md b/docs/MG4_PLATFORM_INSTALL.md new file mode 100644 index 0000000..32f923d --- /dev/null +++ b/docs/MG4_PLATFORM_INSTALL.md @@ -0,0 +1,103 @@ +# Installing a Platform-Signed APK on the MG4 Head Unit + +This documents the reliable way to install a (platform-signed) APK onto the +MG4 SWI69 head unit (Android 9 / SAIC MT2712) over ADB. + +The head unit rejects the standard `adb install` / `pm install` flow with: + +``` +java.io.IOException: Not allowed to install non-system apps on internal storage + at com.android.internal.content.PackageHelper.resolveInstallVolume(...) +``` + +This is not a signature problem — the same `platform.pk8` / `platform.x509.pem` +that signs the already-installed `com.mg4.*` apps signs our APK too (verified by +matching SHA-256 cert digests). The PackageManager simply will not let the +shell UID (2000) stage a non-system package onto internal storage through its +default install path, and `--install-location`, `--force-uuid internal`, `-l` +(forward lock) and session-based `install-create`/`install-write`/`install-commit` +all hit the same wall or fail to open the file (SELinux denies `system_server` +read access to shell-owned files in some flag combinations). + +## Prerequisites + +- The MG4 head unit connected over ADB (`adb devices` lists it). +- A built APK. For a platform-signed build see + [`MG4_PLATFORM_BUILD.md`](./MG4_PLATFORM_BUILD.md) (DiPlay) — the same + `zipalign` + `apksigner sign --key tools/platform.pk8 --cert + tools/platform.x509.pem` step applies here. +- The platform keys in `tools/` (`platform.pk8`, `platform.x509.pem`). + +## The Install Command + +The only flag combination that works on this unit is: + +```bash +adb push .apk /data/local/tmp/update.apk +adb shell "pm install -r -f -d -t /data/local/tmp/update.apk" +``` + +Flags: + +- `-r` — replace the existing package if one is installed. +- `-f` — force install on internal flash (`/data/app/`). +- `-d` — allow a version-code downgrade (debuggable packages only). The + unstable channel bumps `versionCode` per CI build, so a locally built APK + is almost always lower than whatever the OTA last pushed; without `-d` the + install silently fails on a version mismatch. +- `-t` — allow test packages. Unstable/debug builds are marked debuggable, + which the PackageManager treats as a test package. + +The file **must** be pushed as (or renamed to) something under +`/data/local/tmp/`. Other locations (`/sdcard/`, a custom cache dir) fail with +`Can't open file` because `system_server` has no SELinux read access to those +contexts. A failed `pm install` attempt can delete the staged file, so if a +later install says `No such file or directory`, re-push. + +## Verifying the Install + +```bash +adb shell pm path com.evsuite.abrp.unstable +# -> package:/data/app/com.evsuite.abrp.unstable-.../base.apk +``` + +To confirm the platform signature matches the system: + +```bash +BUILD_TOOLS="$ANDROID_HOME/build-tools/36.0.0" +adb pull "$(adb shell pm path com.evsuite.abrp.unstable | sed 's/package://')" /tmp/installed.apk +"$BUILD_TOOLS/apksigner" verify --print-certs /tmp/installed.apk +# SHA-256 cert digest should match tools/platform.x509.pem +``` + +## Uninstalling + +```bash +adb uninstall com.evsuite.abrp.unstable +``` + +Add `-k` to keep data/cache around (useful when re-installing to test without +wiping the local consumption store). + +## End-to-End: Build → Sign → Install + +From the repository root: + +```bash +# 1. Build +./gradlew :app:assembleUnstableDebug + +# 2. Align + platform-sign +SDK="$HOME/Library/Android/sdk" +BT="$SDK/build-tools/36.0.0" +IN=app/build/outputs/apk/unstable/debug/app-unstable-debug.apk +ALIGNED=app/build/outputs/apk/unstable/debug/app-unstable-debug-aligned.apk +OUT=FatihsMG4-unstable-platform.apk +"$BT/zipalign" -f 4 "$IN" "$ALIGNED" +"$BT/apksigner" sign --key tools/platform.pk8 --cert tools/platform.x509.pem --out "$OUT" "$ALIGNED" +"$BT/apksigner" verify --verbose "$OUT" + +# 3. Install on the head unit +adb push "$OUT" /data/local/tmp/update.apk +adb shell "pm install -r -f -d -t /data/local/tmp/update.apk" +```