launcher: a patched Waze, signed with someone else's key, loses the red X and can start as the map app

This commit is contained in:
Seb3thehacker committed 2026-10-15 07:50:34 -07:00
1 parent 0177975bc8
commit db6f1b8e82
3 files changed
+31 -3

No files matched your search

@@ -239,6 +239,7 @@ internal fun launchEntry(entry: Entry, navigator: CarNavigator, frame: CarEnviro
/** The app launcher: every app as an icon grid, grouped Phone, Maps, Music, Messaging, Web, Screen sharing, Settings. */
@Composable
fun CarLauncher() {
val context = LocalContext.current
val navigator = LocalCarNavigator.current
val frame by CarEnvironment.frame.collectAsState()
@@ -254,7 +255,7 @@ fun CarLauncher() {
val id = entry.componentId
return Tile(
entry.label, entry.icon, entry.builtIn?.glyph,
broken = pkg != null && (KnownApps.isBroken(pkg) || (entry.template != null && KnownApps.screenBroken(pkg))),
broken = pkg != null && (KnownApps.isBroken(context, pkg) || (entry.template != null && KnownApps.screenBroken(pkg))),
onLongClick = id?.let { { navigator.showAppMenu(it) } },
) { openApp(entry, id?.let { running[it] }, navigator, frame) }
}
@@ -178,7 +178,7 @@ object CarServices {
_hasNavApps.value = navApps.isNotEmpty()
// Never auto-pick one already known to fail outright - a driver who plugs in should
// land on a map, not on the one tile marked with a red X.
val candidates = navApps.filterNot { KnownApps.isBroken(it.component.packageName) }
val candidates = navApps.filterNot { KnownApps.isBroken(ctx, it.component.packageName) }
val last = CarSettings.lastNav.value
// The one used last, or - first run, nothing on record yet - whichever comes first:
// a driver who plugs in for the first time shouldn't have to go pick one by hand
@@ -1,5 +1,9 @@
package app.seb3thehacker.gearslip.host
import android.content.Context
import android.content.pm.PackageManager
import java.security.MessageDigest
/**
* Apps that have been run through Gearslip from start to finish and behave. The launcher marks
* them so a driver can pick something that works without finding out at the wheel.
@@ -65,7 +69,30 @@ object KnownApps {
"com.generalmagic.magicearth", // Magic Earth: never gets past connecting
)
fun isBroken(packageName: String): Boolean = packageName in broken
fun isBroken(context: Context, packageName: String): Boolean =
packageName in broken && !patched(context, packageName)
/**
* The certificate each broken app's own publisher signs it with. A copy signed with another
* key has been patched to accept Gearslip, like Waze with the waze-gearslip Morphe patch, and
* works.
*/
private val officialSigners = mapOf(
"com.waze" to "03637f6c5d8f604e6fdb79a6ffbfa578de4e318f8da22fc6106665247f8807d7",
)
/** Whether the installed copy is signed by someone other than its publisher. */
private fun patched(context: Context, packageName: String): Boolean {
val official = officialSigners[packageName] ?: return false
val signers = runCatching {
context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES)
.signingInfo?.apkContentsSigners
}.getOrNull() ?: return false
val sha256 = MessageDigest.getInstance("SHA-256")
return signers.isNotEmpty() && signers.none { cert ->
sha256.digest(cert.toByteArray()).joinToString("") { "%02x".format(it) } == official
}
}
/**
* Shown on the launcher with a yellow mark: starts and can be used, but not cleanly enough to