Known-broken apps show with a red X and start unticked instead of being hidden

This commit is contained in:
Seb3thehacker committed 2026-11-06 15:38:11 -08:00
1 parent d857670c9f
commit 38a02974d5
6 files changed
+36 -11

No files matched your search

@@ -149,6 +149,10 @@ internal object LauncherCache {
}
}
}
CarSettings.hideOnFirstSight(tiles.mapNotNull { entry ->
val pkg = (entry.template?.component ?: entry.media?.component)?.packageName ?: entry.messaging?.packageName
entry.componentId?.takeIf { pkg != null && KnownApps.startsHidden(context, pkg, entry.messaging != null) }
})
return tiles.sortedBy { it.label.lowercase() }.also { flow.value = it }
}
}
@@ -69,6 +69,7 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
private const val KEY_PLAYER_TITLE = "car_player_title"
private const val KEY_PLAYER_LEFT = "car_player_left"
private const val KEY_NAV_MIC = "car_nav_mic"
private const val KEY_DEFAULT_HIDDEN = "car_default_hidden"
private const val KEY_THEME = "car_app_theme"
private const val KEY_UI_THEME = "car_ui_theme"
private const val KEY_DARK_STYLE = "car_dark_style"
@@ -586,6 +587,21 @@ private const val KEY_CLUSTER_VIDEO = "cluster_video_enabled"
AppSettings.putString(app, KEY_PINNED, next.joinToString(","))
}
/**
* Unticks each of [ids] the first time it's seen, and never again: a known-broken app starts
* off the drawer, but once the driver ticks it back on it stays on.
*/
fun hideOnFirstSight(ids: List<String>) {
if (!::app.isInitialized) return
val seen = AppSettings.getString(app, KEY_DEFAULT_HIDDEN, "").split(",").filter { it.isNotEmpty() }.toSet()
val fresh = ids.filter { it !in seen }
if (fresh.isEmpty()) return
AppSettings.putString(app, KEY_DEFAULT_HIDDEN, (seen + fresh).joinToString(","))
val next = hiddenAppsFlow.value + fresh
hiddenAppsFlow.value = next
AppSettings.putString(app, KEY_HIDDEN_APPS, next.joinToString(","))
}
fun setAppHidden(id: String, hide: Boolean) {
val next = if (hide) hiddenAppsFlow.value + id else hiddenAppsFlow.value - id
hiddenAppsFlow.value = next
@@ -44,7 +44,6 @@ object CarAppCatalog {
.asSequence()
.filter { it.serviceInfo.packageName != context.packageName }
.filterNot { AndroidAuto.matches(it.serviceInfo.packageName, it.loadLabel(manager).toString()) }
.filterNot { KnownApps.isHidden(it.serviceInfo.packageName) }
.map { resolved ->
val info = resolved.serviceInfo
TemplateApp(
@@ -52,27 +52,34 @@ object KnownApps {
fun screenBroken(packageName: String): Boolean = packageName in brokenScreen
/**
* Registers a car template service but never gives Gearslip a usable screen - left off the
* launcher entirely rather than shown as a tile that goes nowhere.
* Google's own car apps, which never give Gearslip a usable screen. They used to be left off
* the launcher, which looked like a bug to anyone who had them; now they're listed like any
* other broken app, starting unticked (see [startsHidden]).
*/
private val hidden = setOf(
private val google = setOf(
"com.google.android.dialer", // Google Phone
"com.google.android.googlequicksearchbox", // Google Assistant driving surfaces
"com.google.android.apps.maps", // Google Maps: shows as a messenger, and its car UI is Android Auto's own
)
fun isHidden(packageName: String): Boolean = packageName in hidden
/** Shown on the launcher with a red X: known broken, but expected enough that hiding it outright would look like a bug. */
private val broken = setOf(
/** Shown on the launcher with a red X, and unticked to start with. */
private val broken = google + setOf(
"com.google.android.apps.messaging", // Google Messages
"com.waze", // Waze
"com.waze", // Waze: the official app refuses Gearslip; the Morphe-patched one works (see patched())
"com.generalmagic.magicearth", // Magic Earth: never gets past connecting
)
fun isBroken(context: Context, packageName: String): Boolean =
packageName in broken && !patched(context, packageName)
/**
* Whether a tile starts unticked in the phone's list of apps to show, so the drawer opens
* with only what works. Gearslip's own Messages screen works for any messenger, so a broken
* app's messaging tile still shows, except Google Maps', which has no messages worth reading.
*/
fun startsHidden(context: Context, packageName: String, messaging: Boolean): Boolean =
isBroken(context, packageName) && (!messaging || packageName in google)
/**
* 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
@@ -33,7 +33,6 @@ object MediaCatalog {
.asSequence()
.filter { it.serviceInfo.packageName != context.packageName }
.filterNot { AndroidAuto.matches(it.serviceInfo.packageName, it.loadLabel(manager).toString()) }
.filterNot { KnownApps.isHidden(it.serviceInfo.packageName) }
.filter { declaresMedia(manager, it.serviceInfo) }
.map {
val info = it.serviceInfo
@@ -25,7 +25,7 @@ object MessagingCatalog {
.map { it.activityInfo.packageName to it.loadLabel(manager).toString() }
.distinctBy { it.first }
.filter { (pkg, _) -> pkg != context.packageName }
.filterNot { (pkg, label) -> AndroidAuto.matches(pkg, label) || KnownApps.isHidden(pkg) }
.filterNot { (pkg, label) -> AndroidAuto.matches(pkg, label) }
.filter { (pkg, _) -> CarDescriptor.uses(manager, pkg)?.contains("notification") == true }
.map { (pkg, _) ->
val label = runCatching {