Snap for 15862157 from 9531c456b9a72b4a5e8a8d77074bff94d7db35b2 to car-apps-aosp-release

Change-Id: I6e7a2ba9d6230b10158aaa8eff86449415e866a8
diff --git a/aaos-apps-gradle-project/attestation_manifest.json b/aaos-apps-gradle-project/attestation_manifest.json
new file mode 100644
index 0000000..f9144bc
--- /dev/null
+++ b/aaos-apps-gradle-project/attestation_manifest.json
@@ -0,0 +1 @@
+[{"artifact_path": "DriverUI.apk", "attest_archive_contents": false}]
diff --git a/aaos-apps-gradle-project/copy_gradle_output.sh b/aaos-apps-gradle-project/copy_gradle_output.sh
index b9ea07a..7989348 100755
--- a/aaos-apps-gradle-project/copy_gradle_output.sh
+++ b/aaos-apps-gradle-project/copy_gradle_output.sh
@@ -65,6 +65,8 @@
 check_status $?
 cp $GRADLE_OUTPUT_DIR/car-messenger-app/outputs/apk/prod/release/car-messenger-app-prod-release.apk $1/CarMessengerApp.apk
 check_status $?
+cp $GRADLE_OUTPUT_DIR/car-messenger-app/outputs/apk/platformAosp/release/car-messenger-app-platformAosp-release.apk $1/CarMessengerApp_aosp_cert.apk
+check_status $?
 cp $GRADLE_OUTPUT_DIR/PaintBooth/outputs/apk/unbundled/release/PaintBooth-unbundled-release.apk $1/PaintBooth.apk
 check_status $?
 cp $GRADLE_OUTPUT_DIR/oem-token-shared-lib/outputs/apk/unbundled/release/oem-token-shared-lib-unbundled-release.apk $1/oem-token-shared-lib.apk
@@ -81,7 +83,7 @@
 check_status $?
 cp $GRADLE_OUTPUT_DIR/car-bugreport-app/outputs/apk/platformAosp/release/car-bugreport-app-platformAosp-release.apk $1/CarBugReportApp_aosp_cert.apk
 check_status $?
-cp $GRADLE_OUTPUT_DIR/driver-ui/outputs/apk/default/release/driver-ui-default-release-unsigned.apk $1/DriverUI.apk
+cp $GRADLE_OUTPUT_DIR/driver-ui/outputs/apk/platformAosp/debug/driver-ui-platformAosp-debug.apk $1/DriverUI.apk
 check_status $?
 cp $GRADLE_OUTPUT_DIR/driver-ui/outputs/apk/platformAosp/release/driver-ui-platformAosp-release.apk $1/driver-ui-platform-release.apk
 check_status $?
@@ -107,6 +109,8 @@
   check_status $?
   cp $GRADLE_OUTPUT_DIR/car-sensitiveapplock-app/outputs/apk/platformGoogle/release/car-sensitiveapplock-app-platformGoogle-release.apk $1/SensitiveAppLock.apk
   check_status $?
+  cp $GRADLE_OUTPUT_DIR/car-messenger-app/outputs/apk/platformGoogle/release/car-messenger-app-platformGoogle-release.apk $1/CarMessengerApp_google_cert.apk
+  check_status $?
 fi
 
 # AARs
@@ -280,3 +284,8 @@
 
 $JAVA_HOME/bin/jar cvfM $1/jacoco-report-classes-all.jar -C $GRADLE_OUTPUT_DIR/jacoco .
 check_status $?
+
+# Copy attestation manifest for DriverUI.apk
+cp "$SCRIPTS_DIR/attestation_manifest.json" "$1/attestation_manifest.json"
+check_status $?
+
diff --git a/aaos-apps-gradle-project/gradle.properties b/aaos-apps-gradle-project/gradle.properties
index dbe5436..7722b45 100644
--- a/aaos-apps-gradle-project/gradle.properties
+++ b/aaos-apps-gradle-project/gradle.properties
@@ -58,7 +58,7 @@
 aaosApps.buildCfg.buildToolsVersion=36.0.0
 aaosApps.buildCfg.defaultJdkToolchain=17
 aaosApps.buildCfg.ndkVersion=27.0.12077973
-aaosApps.buildCfg.cmakeVersion=3.22.1
+aaosApps.buildCfg.cmakeVersion=4.1.2
 
 # To prevent Jetifier issues with SDV Gateway related jars.
 android.jetifier.ignorelist=libsdvgatewayclient-java.jar
diff --git a/aaos-apps-gradle-project/gradle/libs.versions.toml b/aaos-apps-gradle-project/gradle/libs.versions.toml
index 04b6a8f..a07fb57 100644
--- a/aaos-apps-gradle-project/gradle/libs.versions.toml
+++ b/aaos-apps-gradle-project/gradle/libs.versions.toml
@@ -24,8 +24,8 @@
 coilCompose = "2.4.0"
 composeBom = "2025.05.00" #Sets the versions for all AndroidX Compose dependencies
 coreTesting = "2.2.0"
-designcompose = "0.37.1"
-dexmaker-mockito = "2.28.4"
+designcompose = "0.39.2"
+dexmaker-mockito = "2.28.6"
 espressoCore = "3.6.1"
 glide = "4.12.0"
 googleApiClient = "1.33.2"
diff --git a/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardHostTest.kt b/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardHostTest.kt
index ff944d2..c249e29 100644
--- a/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardHostTest.kt
+++ b/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardHostTest.kt
@@ -43,8 +43,11 @@
 import com.android.car.appcard.internal.AppCardTransport
 import com.android.car.appcard.util.ParcelableUtils
 import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.ListeningExecutorService
+import com.google.common.util.concurrent.MoreExecutors
 import java.util.concurrent.Executor
 import java.util.concurrent.Phaser
+import java.util.concurrent.ScheduledExecutorService
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -158,6 +161,7 @@
                 listener: AppCardTimer.UpdateReadyListener,
                 updateRateMs: Int,
                 fastUpdateRateMs: Int,
+                scheduledExecutorService: ScheduledExecutorService,
             ): AppCardTimer {
                 actualUpdateReadyListener = listener
                 actualUpdateRateMs = updateRateMs
@@ -169,6 +173,14 @@
         object : AppCardHost.UserProvider {
             override fun getCurrentUser() = 10
         }
+    private val executorProvider =
+        object : AppCardHost.ExecutorProvider {
+            override fun getExecutorService(ipcThreadPoolSize: Int): ListeningExecutorService =
+                MoreExecutors.newDirectExecutorService()
+
+            override fun getScheduledExecutorService(): ScheduledExecutorService =
+                mock<ScheduledExecutorService>()
+        }
     private lateinit var appCardHost: AppCardHost
 
     @Before
@@ -185,6 +197,8 @@
                 responseExecutor,
                 appCardTimerProvider,
                 userProvider,
+                executorProvider,
+                8,
             )
 
         verify(packageManager)
diff --git a/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardTimerTest.kt b/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardTimerTest.kt
index 5b712fd..d791b27 100644
--- a/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardTimerTest.kt
+++ b/car-app-card-host-lib/app-card-host/src/androidTest/java/com/android/car/appcard/host/AppCardTimerTest.kt
@@ -19,18 +19,21 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.car.appcard.ImageAppCard
 import com.google.common.truth.Truth.assertThat
-import java.util.Timer
-import java.util.TimerTask
+import java.util.concurrent.ScheduledExecutorService
+import java.util.concurrent.ScheduledFuture
+import java.util.concurrent.TimeUnit
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.kotlin.any
 import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.never
 import org.mockito.kotlin.reset
 import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
 
 @RunWith(AndroidJUnit4::class)
 class AppCardTimerTest {
@@ -47,12 +50,13 @@
             }
         }
     private lateinit var appCardTimer: AppCardTimer
-    private val timer: Timer = mock<Timer>()
-    private val identifier = ApplicationIdentifier(TEST_AUTHORITY, TEST_PACKAGE)
-    private val timerFactory =
-        object : AppCardTimer.TimerFactory {
-            override fun getTimer() = timer
+    private val future: ScheduledFuture<*> = mock<ScheduledFuture<Any>>()
+    private val scheduledExecutorService: ScheduledExecutorService =
+        mock<ScheduledExecutorService> {
+            on { schedule(any(), any(), any()) } doReturn future
+            on { scheduleAtFixedRate(any(), any(), any(), any()) } doReturn future
         }
+    private val identifier = ApplicationIdentifier(TEST_AUTHORITY, TEST_PACKAGE)
 
     @Before
     fun setup() {
@@ -61,15 +65,18 @@
                 updateReadyListener,
                 TEST_UPDATE_RATE_MS,
                 TEST_FAST_UPDATE_RATE_MS,
-                timerFactory,
+                scheduledExecutorService,
             )
     }
 
     @Test
     fun testUpdateAppCard_imageAppCard_timerCancelled() {
         appCardTimer.updateAppCard(AppCardContainer(identifier, ImageAppCardUtility.imageAppCard))
+        reset(future)
 
-        verify(timer).cancel()
+        appCardTimer.updateAppCard(AppCardContainer(identifier, ImageAppCardUtility.imageAppCard))
+
+        verify(future).cancel(eq(false))
     }
 
     @Test
@@ -78,8 +85,13 @@
             AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
         )
 
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
+        val captor = argumentCaptor<Runnable>()
+        verify(scheduledExecutorService)
+            .schedule(
+                captor.capture(),
+                eq(TEST_FAST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
+            )
         captor.firstValue.run()
         assertThat(
                 appCardTimer.isComponentReadyForUpdate(
@@ -93,12 +105,13 @@
     fun testUpdateAppCard_imageAppCard_withProgressBar_appCardTimerScheduled() {
         appCardTimer.updateAppCard(AppCardContainer(identifier, ImageAppCardUtility.imageAppCard))
 
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer)
-            .schedule(
+        val captor = argumentCaptor<Runnable>()
+        verify(scheduledExecutorService)
+            .scheduleAtFixedRate(
                 captor.capture(),
                 eq(TEST_UPDATE_RATE_MS.toLong()),
                 eq(TEST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
             )
         captor.firstValue.run()
         assertThat(actualIdentifier).isEqualTo(identifier)
@@ -117,7 +130,8 @@
 
         appCardTimer.updateAppCard(AppCardContainer(identifier, imageAppCard))
 
-        verify(timer, never()).schedule(any<TimerTask>(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
+        verify(scheduledExecutorService, never())
+            .schedule(any<Runnable>(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()), any())
     }
 
     @Test
@@ -127,12 +141,7 @@
 
     @Test
     fun testIsComponentReadyForUpdate_existingComponent_returnTrue() {
-        appCardTimer.updateAppCard(
-            AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
-        )
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        captor.firstValue.run()
+        setupProgressBarComponentReady()
 
         assertThat(
                 appCardTimer.isComponentReadyForUpdate(
@@ -144,16 +153,18 @@
 
     @Test
     fun testDestroy_timerCancelled() {
+        appCardTimer.updateAppCard(AppCardContainer(identifier, ImageAppCardUtility.imageAppCard))
+
         appCardTimer.destroy()
 
-        verify(timer).cancel()
+        verify(future).cancel(eq(false))
     }
 
     @Test
     fun testResetAppCardTimerAndRequestUpdate_noAppCard_timerCancelNotCalled() {
         appCardTimer.resetAppCardTimerAndRequestUpdate()
 
-        verify(timer, never()).cancel()
+        verify(future, never()).cancel(any())
     }
 
     @Test
@@ -167,40 +178,22 @@
     fun testResetAppCardTimerAndRequestUpdate_noAppCard_timerScheduleNotCalled() {
         appCardTimer.resetAppCardTimerAndRequestUpdate()
 
-        verify(timer, never()).schedule(any<TimerTask>(), any<Long>())
+        verify(scheduledExecutorService, never()).schedule(any<Runnable>(), any(), any())
     }
 
     @Test
     fun testResetAppCardTimerAndRequestUpdate_appCard_timerCancelled() {
         appCardTimer.updateAppCard(AppCardContainer(identifier, ImageAppCardUtility.imageAppCard))
-        reset(timer)
+        reset(future)
 
         appCardTimer.resetAppCardTimerAndRequestUpdate()
 
-        verify(timer).cancel()
+        verify(future).cancel(eq(false))
     }
 
     @Test
     fun testResetAppCardTimerAndRequestUpdate_appCard_componentStatusFalse() {
-        appCardTimer.updateAppCard(
-            AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
-        )
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isFalse()
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        reset(timer)
-        captor.firstValue.run()
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isTrue()
+        setupProgressBarComponentReady()
 
         appCardTimer.resetAppCardTimerAndRequestUpdate()
 
@@ -214,30 +207,18 @@
 
     @Test
     fun testResetAppCardTimerAndRequestUpdate_appCard_componentTimerTaskSetStatusToTrue() {
-        appCardTimer.updateAppCard(
-            AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
-        )
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isFalse()
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        reset(timer)
-        captor.firstValue.run()
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isTrue()
+        setupProgressBarComponentReady()
 
         appCardTimer.resetAppCardTimerAndRequestUpdate()
 
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        captor.secondValue.run()
+        val captor = argumentCaptor<Runnable>()
+        verify(scheduledExecutorService)
+            .schedule(
+                captor.capture(),
+                eq(TEST_FAST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
+            )
+        captor.firstValue.run()
         assertThat(
                 appCardTimer.isComponentReadyForUpdate(
                     ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
@@ -249,16 +230,18 @@
     @Test
     fun testResetAppCardTimerAndRequestUpdate_appCard_appCardTimerTaskCorrectlySet() {
         appCardTimer.updateAppCard(AppCardContainer(identifier, ImageAppCardUtility.imageAppCard))
-        reset(timer)
+        reset(scheduledExecutorService)
+        reConfigureMockExecutor()
 
         appCardTimer.resetAppCardTimerAndRequestUpdate()
 
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer)
-            .schedule(
+        val captor = argumentCaptor<Runnable>()
+        verify(scheduledExecutorService)
+            .scheduleAtFixedRate(
                 captor.capture(),
                 eq(TEST_UPDATE_RATE_MS.toLong()),
                 eq(TEST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
             )
         captor.firstValue.run()
         assertThat(actualIdentifier).isEqualTo(identifier)
@@ -269,35 +252,23 @@
     fun testComponentUpdate_nonExistingComponent_timerNotScheduled() {
         appCardTimer.componentUpdate(TEST_COMPONENT_ID)
 
-        verify(timer, never()).schedule(any<TimerTask>(), any<Long>())
+        verify(scheduledExecutorService, never()).schedule(any<Runnable>(), any(), any())
     }
 
     @Test
     fun testComponentUpdate_existingComponent_timerScheduled() {
-        appCardTimer.updateAppCard(
-            AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
-        )
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isFalse()
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        reset(timer)
-        captor.firstValue.run()
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isTrue()
+        setupProgressBarComponentReady()
 
         appCardTimer.componentUpdate(ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID)
 
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        captor.secondValue.run()
+        val captor = argumentCaptor<Runnable>()
+        verify(scheduledExecutorService)
+            .schedule(
+                captor.capture(),
+                eq(TEST_FAST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
+            )
+        captor.firstValue.run()
         assertThat(
                 appCardTimer.isComponentReadyForUpdate(
                     ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
@@ -308,18 +279,35 @@
 
     @Test
     fun testComponentUpdate_existingComponent_componentUpdateStatusIsFalse() {
-        appCardTimer.updateAppCard(
-            AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
-        )
+        setupProgressBarComponentReady()
+
+        appCardTimer.componentUpdate(ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID)
+
+        verify(scheduledExecutorService)
+            .schedule(
+                any<Runnable>(),
+                eq(TEST_FAST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
+            )
         assertThat(
                 appCardTimer.isComponentReadyForUpdate(
                     ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
                 )
             )
             .isFalse()
-        val captor = argumentCaptor<TimerTask>()
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        reset(timer)
+    }
+
+    private fun setupProgressBarComponentReady() {
+        appCardTimer.updateAppCard(
+            AppCardContainer(identifier, ImageAppCardUtility.progressBarButtonCard)
+        )
+        val captor = argumentCaptor<Runnable>()
+        verify(scheduledExecutorService)
+            .schedule(
+                captor.capture(),
+                eq(TEST_FAST_UPDATE_RATE_MS.toLong()),
+                eq(TimeUnit.MILLISECONDS),
+            )
         captor.firstValue.run()
         assertThat(
                 appCardTimer.isComponentReadyForUpdate(
@@ -327,16 +315,15 @@
                 )
             )
             .isTrue()
+        reset(scheduledExecutorService)
+        reConfigureMockExecutor()
+    }
 
-        appCardTimer.componentUpdate(ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID)
-
-        verify(timer).schedule(captor.capture(), eq(TEST_FAST_UPDATE_RATE_MS.toLong()))
-        assertThat(
-                appCardTimer.isComponentReadyForUpdate(
-                    ImageAppCardUtility.TEST_PROGRESS_BAR_COMPONENT_ID
-                )
-            )
-            .isFalse()
+    private fun reConfigureMockExecutor() {
+        doReturn(future).whenever(scheduledExecutorService).schedule(any(), any(), any())
+        doReturn(future)
+            .whenever(scheduledExecutorService)
+            .scheduleAtFixedRate(any(), any(), any(), any())
     }
 
     companion object {
diff --git a/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardHost.kt b/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardHost.kt
index e17f227..42bb821 100644
--- a/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardHost.kt
+++ b/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardHost.kt
@@ -25,7 +25,6 @@
 import android.content.IntentFilter
 import android.content.pm.PackageManager
 import android.content.pm.ProviderInfo
-import android.os.Build
 import android.os.Bundle
 import android.os.DeadObjectException
 import android.os.UserHandle
@@ -40,12 +39,14 @@
 import com.android.car.appcard.internal.AppCardTransport
 import com.google.common.util.concurrent.FutureCallback
 import com.google.common.util.concurrent.Futures
+import com.google.common.util.concurrent.ListeningExecutorService
 import com.google.common.util.concurrent.MoreExecutors
 import com.google.protobuf.InvalidProtocolBufferException
 import java.util.concurrent.ConcurrentHashMap
 import java.util.concurrent.ConcurrentMap
 import java.util.concurrent.Executor
 import java.util.concurrent.Executors
+import java.util.concurrent.ScheduledExecutorService
 import java.util.function.Consumer
 
 class AppCardHost
@@ -56,6 +57,8 @@
     private val responseExecutor: Executor,
     private val timerProvider: AppCardTimerProvider,
     private val userProvider: UserProvider,
+    private val executorProvider: ExecutorProvider,
+    ipcThreadPoolSize: Int,
 ) : UpdateReadyListener, AppCardObserverCallback {
 
     constructor(
@@ -63,6 +66,7 @@
         updateRate: Int,
         fastUpdateRate: Int,
         responseExecutor: Executor,
+        ipcThreadPoolSize: Int = DEFAULT_IPC_THREAD_COUNT,
     ) : this(
         c,
         updateRate,
@@ -73,16 +77,27 @@
                 listener: UpdateReadyListener,
                 updateRateMs: Int,
                 fastUpdateRateMs: Int,
-            ) = AppCardTimer(listener, updateRateMs, fastUpdateRateMs)
+                scheduledExecutorService: ScheduledExecutorService,
+            ) = AppCardTimer(listener, updateRateMs, fastUpdateRateMs, scheduledExecutorService)
         },
         object : UserProvider {
             override fun getCurrentUser() = ActivityManager.getCurrentUser()
         },
+        object : ExecutorProvider {
+            override fun getExecutorService(ipcThreadPoolSize: Int): ListeningExecutorService =
+                MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ipcThreadPoolSize))
+
+            override fun getScheduledExecutorService(): ScheduledExecutorService =
+                Executors.newSingleThreadScheduledExecutor()
+        },
+        ipcThreadPoolSize,
     )
 
     private val listeners: MutableSet<AppCardListener>
     private val idBrokerMap: ConcurrentMap<ApplicationIdentifier, BrokerWrapper>
-    private val executorService = MoreExecutors.listeningDecorator(Executors.newWorkStealingPool())
+    private val authorityToIdentifierMap: ConcurrentMap<String, ApplicationIdentifier>
+    private val executorService: ListeningExecutorService
+    private val scheduledExecutorService: ScheduledExecutorService
     private val packageManager: PackageManager
     private val contentResolver: ContentResolver
     private val brokerFactory: BrokerFactory
@@ -100,6 +115,10 @@
 
         listeners = HashSet()
         idBrokerMap = ConcurrentHashMap()
+        authorityToIdentifierMap = ConcurrentHashMap()
+
+        executorService = executorProvider.getExecutorService(ipcThreadPoolSize)
+        scheduledExecutorService = executorProvider.getScheduledExecutorService()
 
         val expectedBrokerPermission =
             context.resources.getString(com.android.car.appcard.R.string.host_permission)
@@ -113,6 +132,7 @@
             )
         brokerFactory.connectToAllCompatibleApplications().forEach {
             idBrokerMap[it.key] = BrokerWrapper(it.value, it.key)
+            authorityToIdentifierMap[it.key.authority] = it.key
         }
 
         setupAppChangeReceiver()
@@ -161,6 +181,7 @@
         synchronized(idBrokerMap) {
             brokerFactory.refreshCompatibleApplication(idBrokerMap.keys).forEach {
                 idBrokerMap[it.key] = BrokerWrapper(it.value, it.key)
+                authorityToIdentifierMap[it.key.authority] = it.key
             }
         }
     }
@@ -180,6 +201,7 @@
             )
 
             idBrokerMap.clear()
+            authorityToIdentifierMap.clear()
         }
     }
 
@@ -192,6 +214,8 @@
             synchronized(listeners) { listeners.clear() }
 
             closeAllApplicationConnections()
+            executorService.shutdownNow()
+            scheduledExecutorService.shutdownNow()
         }
     }
 
@@ -326,6 +350,18 @@
 
             brokerWrapper.activeAppCardMap.clear()
             idBrokerMap.remove(identifier)
+            authorityToIdentifierMap.remove(identifier.authority)
+
+            synchronized(listeners) {
+                listeners.forEach(
+                    Consumer { appCardListener: AppCardListener ->
+                        appCardListener.onProviderRemoved(
+                            identifier.packageName,
+                            identifier.authority,
+                        )
+                    }
+                )
+            }
         }
     }
 
@@ -680,96 +716,13 @@
                     listener = this,
                     updateRateMs = updateRateMs,
                     fastUpdateRateMs = fastUpdateRateMs,
+                    scheduledExecutorService = scheduledExecutorService,
                 )
             timer.updateAppCard(AppCardContainer(identifier, appCard))
             activeAppCardMap.put(appCard.id, ActiveAppCard(appCard, timer))
         }
     }
 
-    private fun retrieveAppCardComponentUpdate(
-        brokerWrapper: BrokerWrapper,
-        activeAppCard: ActiveAppCard,
-        identifier: ApplicationIdentifier,
-        appCardId: String,
-        componentId: String,
-    ) {
-        synchronized(idBrokerMap) {
-            val broker = brokerWrapper.broker
-            val timer = activeAppCard.appCardTimer
-            val listenableFuture =
-                executorService.submit<AppCardComponentContainer> {
-                    val bundle = Bundle()
-                    bundle.apply {
-                        putString(AppCardContentProvider.BUNDLE_KEY_APP_CARD_ID, appCardId)
-                        putString(
-                            AppCardContentProvider.BUNDLE_KEY_APP_CARD_COMPONENT_ID,
-                            componentId,
-                        )
-                    }
-
-                    val appCardTransport =
-                        try {
-                            broker.getAppCardTransport(
-                                identifier,
-                                errorId = "$appCardId#$componentId",
-                                bundle,
-                                AppCardMessageConstants.MSG_APP_CARD_COMPONENT_UPDATE,
-                            )
-                        } catch (exception: Exception) {
-                            if (exception is ContentProviderBroker.ContentProviderBrokerException) {
-                                if (exception.cause is DeadObjectException) {
-                                    handleInvalidBroker(identifier)
-                                }
-                            }
-
-                            throw exception
-                        }
-
-                    val component =
-                        appCardTransport.component
-                            ?: throw AppCardHostException(
-                                AppCardMessageConstants.MSG_APP_CARD_COMPONENT_UPDATE,
-                                id = "$appCardId#$componentId",
-                                IllegalStateException("App card component missing from transport"),
-                            )
-                    timer.componentUpdate(component.componentId)
-
-                    AppCardComponentContainer(identifier, appCardId, component)
-                }
-
-            Futures.addCallback(
-                listenableFuture,
-                object : FutureCallback<AppCardComponentContainer> {
-                    override fun onSuccess(appCardComponentContainer: AppCardComponentContainer) {
-                        synchronized(listeners) {
-                            listeners.forEach(
-                                Consumer { appCardListener: AppCardListener ->
-                                    appCardListener.onComponentReceived(appCardComponentContainer)
-                                }
-                            )
-                        }
-                    }
-
-                    override fun onFailure(throwable: Throwable) {
-                        Log.e(TAG, throwable.message, throwable)
-
-                        synchronized(listeners) {
-                            listeners.forEach(
-                                Consumer { appCardListener: AppCardListener ->
-                                    appCardListener.onPackageCommunicationError(
-                                        identifier,
-                                        throwable,
-                                    )
-                                }
-                            )
-                        }
-                    }
-                },
-                responseExecutor,
-            )
-        }
-    }
-
     private fun createUserContext(context: Context, userId: Int): Context {
         val flags = 0
         return context.createContextAsUser(UserHandle.of(userId), flags)
@@ -795,20 +748,20 @@
     @VisibleForTesting
     internal fun handlePackageRemovedOrDisabled(packageName: String, authority: String?) {
         synchronized(idBrokerMap) {
-            var isRemoved = false
-            idBrokerMap.entries.removeIf { (key, value) ->
-                authority?.let { if (!key.containsAuthority(it)) return@removeIf false }
+            val wasRemoved =
+                idBrokerMap.entries.removeIf { (key, value) ->
+                    authority?.let { if (!key.containsAuthority(it)) return@removeIf false }
 
-                if (!key.containsPackage(packageName)) return@removeIf false
+                    if (!key.containsPackage(packageName)) return@removeIf false
 
-                value.broker.close()
-                value.activeAppCardMap.clear()
-                isRemoved = true
+                    value.broker.close()
+                    value.activeAppCardMap.clear()
+                    authorityToIdentifierMap.remove(key.authority)
 
-                true
-            }
+                    true
+                }
 
-            if (!isRemoved) return
+            if (!wasRemoved) return
 
             synchronized(listeners) {
                 listeners.forEach(
@@ -909,11 +862,26 @@
     @VisibleForTesting
     internal fun handleUserChange() {
         synchronized(idBrokerMap) {
+            val identifiers = idBrokerMap.keys.toList()
             closeAllApplicationConnections()
             currentUser = userProvider.getCurrentUser()
-            idBrokerMap.clear()
+
+            synchronized(listeners) {
+                identifiers.forEach { identifier ->
+                    listeners.forEach(
+                        Consumer { appCardListener: AppCardListener ->
+                            appCardListener.onProviderRemoved(
+                                identifier.packageName,
+                                identifier.authority,
+                            )
+                        }
+                    )
+                }
+            }
+
             brokerFactory.connectToAllCompatibleApplications().forEach {
                 idBrokerMap[it.key] = BrokerWrapper(it.value, it.key)
+                authorityToIdentifierMap[it.key.authority] = it.key
             }
         }
     }
@@ -996,42 +964,127 @@
         id: String,
         componentId: String,
     ) {
-        synchronized(idBrokerMap) {
-            val identifier =
-                idBrokerMap.keys
-                    .stream()
-                    .filter { i: ApplicationIdentifier -> i.containsAuthority(authority) }
-                    .findFirst()
+        executorService.execute {
+            val updateInfo =
+                synchronized(idBrokerMap) {
+                    val identifier = authorityToIdentifierMap[authority] ?: return@synchronized null
 
-            val isEmpty =
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-                    identifier.isEmpty
-                } else {
-                    !identifier.isPresent
+                    val brokerWrapper = idBrokerMap[identifier] ?: return@synchronized null
+                    val activeAppCard =
+                        brokerWrapper.activeAppCardMap[id] ?: return@synchronized null
+
+                    if (!activeAppCard.appCardTimer.isComponentReadyForUpdate(componentId)) {
+                        return@synchronized null
+                    }
+                    Triple(identifier, brokerWrapper, activeAppCard)
                 }
-            if (isEmpty) return
 
-            val brokerWrapper = idBrokerMap[identifier.get()] ?: return
-            val cacheTimer = brokerWrapper.activeAppCardMap[id] ?: return
+            updateInfo?.let { (identifier, brokerWrapper, activeAppCard) ->
+                val broker = brokerWrapper.broker
+                val timer = activeAppCard.appCardTimer
 
-            if (!cacheTimer.appCardTimer.isComponentReadyForUpdate(componentId)) return
+                val bundle = Bundle()
+                bundle.apply {
+                    putString(AppCardContentProvider.BUNDLE_KEY_APP_CARD_ID, id)
+                    putString(AppCardContentProvider.BUNDLE_KEY_APP_CARD_COMPONENT_ID, componentId)
+                }
 
-            retrieveAppCardComponentUpdate(
-                brokerWrapper,
-                cacheTimer,
-                identifier.get(),
-                id,
-                componentId,
-            )
+                try {
+                    val appCardTransport =
+                        broker.getAppCardTransport(
+                            identifier,
+                            errorId = "$id#$componentId",
+                            bundle,
+                            AppCardMessageConstants.MSG_APP_CARD_COMPONENT_UPDATE,
+                        )
+
+                    val component =
+                        appCardTransport.component
+                            ?: throw AppCardHostException(
+                                AppCardMessageConstants.MSG_APP_CARD_COMPONENT_UPDATE,
+                                id = "$id#$componentId",
+                                IllegalStateException("App card component missing from transport"),
+                            )
+
+                    // Re-verify that the app card and its broker are still active after the
+                    // long-running IPC call, ensuring that we use the most current state
+                    // and avoid race conditions.
+                    synchronized(idBrokerMap) {
+                        val currentIdentifier =
+                            authorityToIdentifierMap[authority] ?: return@synchronized
+                        val currentBrokerWrapper =
+                            idBrokerMap[currentIdentifier] ?: return@synchronized
+                        val currentActiveCard =
+                            currentBrokerWrapper.activeAppCardMap[id] ?: return@synchronized
+
+                        currentActiveCard.appCardTimer.componentUpdate(component.componentId)
+
+                        val appCardComponentContainer =
+                            AppCardComponentContainer(currentIdentifier, id, component)
+
+                        responseExecutor.execute {
+                            synchronized(listeners) {
+                                listeners.forEach(
+                                    Consumer { appCardListener: AppCardListener ->
+                                        appCardListener.onComponentReceived(
+                                            appCardComponentContainer
+                                        )
+                                    }
+                                )
+                            }
+                        }
+                    }
+                } catch (exception: Exception) {
+                    val identifierToReport =
+                        synchronized(idBrokerMap) {
+                            val freshIdentifier = authorityToIdentifierMap[authority]
+                            val identifierForError = freshIdentifier ?: identifier
+
+                            if (
+                                freshIdentifier != null &&
+                                    exception is
+                                        ContentProviderBroker.ContentProviderBrokerException &&
+                                    exception.cause is DeadObjectException &&
+                                    idBrokerMap[freshIdentifier] === brokerWrapper
+                            ) {
+                                handleInvalidBroker(freshIdentifier)
+                            }
+                            identifierForError
+                        }
+
+                    Log.e(TAG, exception.message, exception)
+
+                    responseExecutor.execute {
+                        synchronized(listeners) {
+                            listeners.forEach(
+                                Consumer { appCardListener: AppCardListener ->
+                                    appCardListener.onPackageCommunicationError(
+                                        identifierToReport,
+                                        exception,
+                                    )
+                                }
+                            )
+                        }
+                    }
+                }
+            }
         }
     }
 
+    /** Internal interface to abstract out executors from tests */
+    internal interface ExecutorProvider {
+        fun getExecutorService(ipcThreadPoolSize: Int): ListeningExecutorService
+
+        fun getScheduledExecutorService(): ScheduledExecutorService
+    }
+
     /** Internal interface to abstract out timers from tests */
     internal interface AppCardTimerProvider {
         fun getNewTimer(
             listener: UpdateReadyListener,
             updateRateMs: Int,
             fastUpdateRateMs: Int,
+            scheduledExecutorService: ScheduledExecutorService,
         ): AppCardTimer
     }
 
@@ -1051,6 +1104,7 @@
     companion object {
         private const val TAG = "AppCardHost"
         private const val DATA_SCHEME_PACKAGE = "package"
+        private const val DEFAULT_IPC_THREAD_COUNT = 8
 
         @Throws(AppCardHostException::class)
         private fun getHostAppCardsFromTransport(
diff --git a/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardTimer.kt b/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardTimer.kt
index 55150a7..fc3f104 100644
--- a/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardTimer.kt
+++ b/car-app-card-host-lib/app-card-host/src/main/java/com/android/car/appcard/host/AppCardTimer.kt
@@ -17,28 +17,30 @@
 package com.android.car.appcard.host
 
 import com.android.car.appcard.ImageAppCard
-import java.util.Timer
-import java.util.TimerTask
 import java.util.concurrent.ConcurrentHashMap
 import java.util.concurrent.ConcurrentMap
+import java.util.concurrent.ScheduledExecutorService
+import java.util.concurrent.ScheduledFuture
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
 import java.util.function.Consumer
 
 internal class AppCardTimer(
     private val listener: UpdateReadyListener,
     private val updateRateMs: Int,
     private val fastUpdateRateMs: Int,
-    private val timerFactory: TimerFactory =
-        object : TimerFactory {
-            override fun getTimer() = Timer()
-        },
+    private val scheduledExecutorService: ScheduledExecutorService,
 ) {
     private val componentUpdateStatusMap: ConcurrentMap<String, Boolean>
+    private val componentUpdateFutureMap: ConcurrentMap<String, ScheduledFuture<*>>
+    private val lock = Any()
     private var identifier: ApplicationIdentifier? = null
     private var appCardId: String? = null
-    private var refreshTimer = timerFactory.getTimer()
+    private var refreshFuture: ScheduledFuture<*>? = null
 
     init {
         componentUpdateStatusMap = ConcurrentHashMap()
+        componentUpdateFutureMap = ConcurrentHashMap()
     }
 
     fun updateAppCard(appCardContainer: AppCardContainer) {
@@ -48,9 +50,8 @@
     }
 
     private fun handleImageAppCardUpdate(imageAppCard: ImageAppCard, id: ApplicationIdentifier) {
-        synchronized(lock = this) {
-            refreshTimer.cancel()
-            refreshTimer = timerFactory.getTimer()
+        synchronized(lock) {
+            cancelAllFutures()
 
             componentUpdateStatusMap.clear()
 
@@ -59,35 +60,41 @@
 
             imageAppCard.progressBar?.let {
                 componentUpdateStatusMap[it.componentId] = false
-                refreshTimer.schedule(
-                    object : TimerTask() {
-                        override fun run() {
-                            componentUpdateStatusMap[it.componentId] = true
-                        }
-                    },
-                    fastUpdateRateMs.toLong(),
-                )
+                val componentId = it.componentId
+                val futureRef = AtomicReference<ScheduledFuture<*>>()
+                val future =
+                    scheduledExecutorService.schedule(
+                        {
+                            synchronized(lock) {
+                                if (componentUpdateFutureMap[componentId] === futureRef.get()) {
+                                    componentUpdateStatusMap[componentId] = true
+                                    componentUpdateFutureMap.remove(componentId)
+                                }
+                            }
+                        },
+                        fastUpdateRateMs.toLong(),
+                        TimeUnit.MILLISECONDS,
+                    )
+                futureRef.set(future)
+                componentUpdateFutureMap[componentId] = future
             }
 
-            refreshTimer.schedule(
-                object : TimerTask() {
-                    override fun run() {
-                        listener.appCardIsReadyForUpdate(identifier, appCardId)
-                    }
-                },
-                updateRateMs.toLong(),
-                updateRateMs.toLong(),
-            )
+            refreshFuture =
+                scheduledExecutorService.scheduleAtFixedRate(
+                    { listener.appCardIsReadyForUpdate(identifier, appCardId) },
+                    updateRateMs.toLong(),
+                    updateRateMs.toLong(),
+                    TimeUnit.MILLISECONDS,
+                )
         }
     }
 
     fun resetAppCardTimerAndRequestUpdate() {
-        synchronized(lock = this) {
+        synchronized(lock) {
             appCardId ?: return
             identifier ?: return
 
-            refreshTimer.cancel()
-            refreshTimer = timerFactory.getTimer()
+            cancelAllFutures()
 
             listener.appCardIsReadyForUpdate(identifier, appCardId)
 
@@ -95,67 +102,85 @@
 
             componentUpdateStatusMap.keys.forEach(
                 Consumer { componentId: String ->
-                    refreshTimer.schedule(
-                        object : TimerTask() {
-                            override fun run() {
-                                componentUpdateStatusMap[componentId] = true
-                            }
-                        },
-                        fastUpdateRateMs.toLong(),
-                    )
+                    val futureRef = AtomicReference<ScheduledFuture<*>>()
+                    val future =
+                        scheduledExecutorService.schedule(
+                            {
+                                synchronized(lock) {
+                                    if (componentUpdateFutureMap[componentId] === futureRef.get()) {
+                                        componentUpdateStatusMap[componentId] = true
+                                        componentUpdateFutureMap.remove(componentId)
+                                    }
+                                }
+                            },
+                            fastUpdateRateMs.toLong(),
+                            TimeUnit.MILLISECONDS,
+                        )
+                    futureRef.set(future)
+                    componentUpdateFutureMap[componentId] = future
                 }
             )
 
-            refreshTimer.schedule(
-                object : TimerTask() {
-                    override fun run() {
-                        listener.appCardIsReadyForUpdate(identifier, appCardId)
-                    }
-                },
-                updateRateMs.toLong(),
-                updateRateMs.toLong(),
-            )
+            refreshFuture =
+                scheduledExecutorService.scheduleAtFixedRate(
+                    { listener.appCardIsReadyForUpdate(identifier, appCardId) },
+                    updateRateMs.toLong(),
+                    updateRateMs.toLong(),
+                    TimeUnit.MILLISECONDS,
+                )
         }
     }
 
     fun isComponentReadyForUpdate(componentId: String): Boolean {
-        synchronized(lock = this) {
+        synchronized(lock) {
             val defaultValue = false
             return componentUpdateStatusMap.getOrDefault(componentId, defaultValue)
         }
     }
 
     fun destroy() {
-        synchronized(lock = this) {
-            refreshTimer.cancel()
-            refreshTimer = timerFactory.getTimer()
-
+        synchronized(lock) {
+            cancelAllFutures()
             componentUpdateStatusMap.clear()
         }
     }
 
     fun componentUpdate(componentId: String) {
-        synchronized(lock = this) {
-            if (!componentUpdateStatusMap.containsKey(componentId)) return
+        synchronized(lock) {
+            if (componentUpdateStatusMap[componentId] != true) {
+                return
+            }
 
             componentUpdateStatusMap[componentId] = false
+            componentUpdateFutureMap.remove(componentId)?.cancel(false)
 
-            refreshTimer.schedule(
-                object : TimerTask() {
-                    override fun run() {
-                        componentUpdateStatusMap[componentId] = true
-                    }
-                },
-                fastUpdateRateMs.toLong(),
-            )
+            val futureRef = AtomicReference<ScheduledFuture<*>>()
+            val future =
+                scheduledExecutorService.schedule(
+                    {
+                        synchronized(lock) {
+                            if (componentUpdateFutureMap[componentId] === futureRef.get()) {
+                                componentUpdateStatusMap[componentId] = true
+                                componentUpdateFutureMap.remove(componentId)
+                            }
+                        }
+                    },
+                    fastUpdateRateMs.toLong(),
+                    TimeUnit.MILLISECONDS,
+                )
+            futureRef.set(future)
+            componentUpdateFutureMap[componentId] = future
         }
     }
 
+    private fun cancelAllFutures() {
+        refreshFuture?.cancel(false)
+        refreshFuture = null
+        componentUpdateFutureMap.values.forEach { it.cancel(false) }
+        componentUpdateFutureMap.clear()
+    }
+
     internal interface UpdateReadyListener {
         fun appCardIsReadyForUpdate(identifier: ApplicationIdentifier?, appCardId: String?)
     }
-
-    internal interface TimerFactory {
-        fun getTimer(): Timer
-    }
 }
diff --git a/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/AppCardContentProvider.kt b/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/AppCardContentProvider.kt
index 87a4afe..cf53a5d 100644
--- a/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/AppCardContentProvider.kt
+++ b/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/AppCardContentProvider.kt
@@ -292,40 +292,45 @@
     private fun getMethod(uri: Uri) = uri.pathSegments[0]
 
     final override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
-        synchronized(lock) {
-            var id: String? = null
-            var componentId: String? = null
-            var interactionId: String? = null
-            var appCardContext: AppCardContext? = null
+        try {
+            synchronized(lock) {
+                var id: String? = null
+                var componentId: String? = null
+                var interactionId: String? = null
+                var appCardContext: AppCardContext? = null
 
-            extras?.let {
-                val defaultValue = null
-                id = it.getString(BUNDLE_KEY_APP_CARD_ID, defaultValue)
-                componentId = it.getString(BUNDLE_KEY_APP_CARD_COMPONENT_ID, defaultValue)
-                interactionId = it.getString(BUNDLE_KEY_APP_CARD_INTERACTION_ID, defaultValue)
-                val appCardContextBundle = it.getBundle(BUNDLE_KEY_APP_CARD_CONTEXT)
-                appCardContext = fromBundle(appCardContextBundle)
+                extras?.let {
+                    val defaultValue = null
+                    id = it.getString(BUNDLE_KEY_APP_CARD_ID, defaultValue)
+                    componentId = it.getString(BUNDLE_KEY_APP_CARD_COMPONENT_ID, defaultValue)
+                    interactionId = it.getString(BUNDLE_KEY_APP_CARD_INTERACTION_ID, defaultValue)
+                    val appCardContextBundle = it.getBundle(BUNDLE_KEY_APP_CARD_CONTEXT)
+                    appCardContext = fromBundle(appCardContextBundle)
+                }
+
+                var bundle: Bundle? = null
+                when (method) {
+                    AppCardMessageConstants.MSG_APP_CARD_COMPONENT_UPDATE ->
+                        bundle = handleAppCardComponentUpdate(id, componentId)
+
+                    AppCardMessageConstants.MSG_APP_CARD_REMOVED -> removeAppCard(id)
+
+                    AppCardMessageConstants.MSG_APP_CARD_INTERACTION ->
+                        handleInteraction(id, componentId, interactionId)
+
+                    AppCardMessageConstants.MSG_APP_CARD_CONTEXT_UPDATE ->
+                        handleAppCardContextUpdate(id, appCardContext)
+
+                    AppCardMessageConstants.MSG_CLOSE_PROVIDER -> handleClose()
+
+                    else -> Log.e(TAG, "Unrecognized method: $method")
+                }
+
+                return bundle
             }
-
-            var bundle: Bundle? = null
-            when (method) {
-                AppCardMessageConstants.MSG_APP_CARD_COMPONENT_UPDATE ->
-                    bundle = handleAppCardComponentUpdate(id, componentId)
-
-                AppCardMessageConstants.MSG_APP_CARD_REMOVED -> removeAppCard(id)
-
-                AppCardMessageConstants.MSG_APP_CARD_INTERACTION ->
-                    handleInteraction(id, componentId, interactionId)
-
-                AppCardMessageConstants.MSG_APP_CARD_CONTEXT_UPDATE ->
-                    handleAppCardContextUpdate(id, appCardContext)
-
-                AppCardMessageConstants.MSG_CLOSE_PROVIDER -> handleClose()
-
-                else -> Log.e(TAG, "Unrecognized method: $method")
-            }
-
-            return bundle
+        } catch (e: Exception) {
+            Log.e(TAG, "Exception occurred during call ($method)", e)
+            return null
         }
     }
 
@@ -470,17 +475,16 @@
         }
 
         latestAppCard[appCard.id] = appCard
-        activeAppCardCountMap[id] =
-            (activeAppCardCountMap[id]?.let { it + 1 })
-                ?: run {
-                    if (dispatcher.getDesiredState() != Lifecycle.Event.ON_RESUME) {
-                        if (dispatcher.getDesiredState() != Lifecycle.Event.ON_START)
-                            dispatcher.queueOnStart()
-
-                        dispatcher.queueOnResume()
-                    }
-                    1 // run's return value
+        activeAppCardCountMap.compute(id) { _, count ->
+            val newCount = (count ?: 0) + 1
+            if (newCount == 1 && dispatcher.getDesiredState() != Lifecycle.Event.ON_RESUME) {
+                if (dispatcher.getDesiredState() != Lifecycle.Event.ON_START) {
+                    dispatcher.queueOnStart()
                 }
+                dispatcher.queueOnResume()
+            }
+            newCount
+        }
         appCardIdComponentMap[id] = getComponentMapFromAppCard(appCard)
 
         return appCard
@@ -493,29 +497,42 @@
                 return
             }
 
-        val defaultValue = 0
-        var count = activeAppCardCountMap.getOrDefault(id, defaultValue)
-
-        when (count) {
-            0 -> Log.e(TAG, "App card remove requested for an inactive app card")
-            1 -> {
-                activeAppCardCountMap.remove(id)
-                appCardIdComponentMap.remove(id)
-                latestAppCard.remove(id)
-                onAppCardRemoved(id)
-
-                if (
-                    activeAppCardCountMap.isEmpty() &&
-                        dispatcher.getDesiredState() != Lifecycle.Event.ON_STOP
-                ) {
-                    if (dispatcher.getDesiredState() != Lifecycle.Event.ON_PAUSE)
-                        dispatcher.queueOnPause()
-
-                    dispatcher.queueOnStop()
+        var removed = false
+        var wasInactive = false
+        activeAppCardCountMap.compute(id) { _, count ->
+            when (count) {
+                null,
+                0 -> {
+                    wasInactive = true
+                    null
                 }
+                1 -> {
+                    removed = true
+                    null
+                }
+                else -> count - 1
             }
+        }
 
-            else -> activeAppCardCountMap[id] = --count
+        if (wasInactive) {
+            Log.e(TAG, "App card remove requested for an inactive app card")
+            return
+        }
+
+        if (removed) {
+            appCardIdComponentMap.remove(id)
+            latestAppCard.remove(id)
+            onAppCardRemoved(id)
+
+            if (
+                activeAppCardCountMap.isEmpty() &&
+                    dispatcher.getDesiredState() != Lifecycle.Event.ON_STOP
+            ) {
+                if (dispatcher.getDesiredState() != Lifecycle.Event.ON_PAUSE) {
+                    dispatcher.queueOnPause()
+                }
+                dispatcher.queueOnStop()
+            }
         }
     }
 
diff --git a/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Button.kt b/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Button.kt
index 8e87038..ee34ed0 100644
--- a/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Button.kt
+++ b/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Button.kt
@@ -123,12 +123,11 @@
     }
 
     override fun hashCode(): Int {
-        var result = text?.hashCode() ?: 0
+        var result = super.hashCode()
+        result = 31 * result + (text?.hashCode() ?: 0)
         result = 31 * result + (image?.hashCode() ?: 0)
         result = 31 * result + buttonType.hashCode()
         result = 31 * result + (onClickListener?.hashCode() ?: 0)
-        result = 31 * result + (text?.hashCode() ?: 0)
-        result = 31 * result + (image?.hashCode() ?: 0)
         result = 31 * result + (intent?.hashCode() ?: 0)
         return result
     }
diff --git a/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Image.kt b/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Image.kt
index 85f5c18..9866c67 100644
--- a/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Image.kt
+++ b/car-app-card-lib/app-card/src/main/java/com/android/car/appcard/component/Image.kt
@@ -21,41 +21,53 @@
 import com.android.car.appcard.internal.proto.Image.ImageMessage
 import com.google.protobuf.ByteString
 import java.io.ByteArrayOutputStream
+import java.nio.ByteBuffer
 import java.security.MessageDigest
+import java.util.Arrays
 
 /**
  * Image is a component that contains an image and information on how the image should be displayed.
  */
 class Image private constructor(builder: Builder) : Component(builder) {
     /** @return [ContentScale] */
+    @Volatile
     var contentScale: ContentScale
         private set
 
     /** @return [ColorFilter] */
+    @Volatile
     var colorFilter: ColorFilter
         private set
 
     /** @return [android.graphics.Bitmap] */
+    @Volatile
     var imageData: Bitmap?
         private set
 
-    private var imageHashString: String? = null
+    @Volatile private var imageHash: ByteArray? = null
+    @Volatile private var capturedGenerationId: Int = -1
+    @Volatile private var compressedData: ByteArray? = null
+    @Volatile private var cachedHashCode: Int? = null
+    private val lock = Any()
 
     init {
         imageData = builder.imageData
         contentScale = builder.contentScale
         colorFilter = builder.colorFilter
-        updateImageHash()
+        updateImageHashAndCache()
     }
 
     /** @return protobuf message */
-    fun toMessage(): ImageMessage =
-        ImageMessage.newBuilder()
-            .setComponentId(componentId)
-            .setImage(imageData?.let { ByteString.copyFrom(toByteArray(it)) })
-            .setContentScale(toContentScale(contentScale))
-            .setColorFilter(toColorFilter(colorFilter))
-            .build()
+    fun toMessage(): ImageMessage {
+        synchronized(lock) {
+            return ImageMessage.newBuilder()
+                .setComponentId(componentId)
+                .setImage(getCompressedData()?.let { ByteString.copyFrom(it) })
+                .setContentScale(toContentScale(contentScale))
+                .setColorFilter(toColorFilter(colorFilter))
+                .build()
+        }
+    }
 
     /** @return protobuf byte array */
     override fun toByteArray(): ByteArray = toMessage().toByteArray()
@@ -63,43 +75,116 @@
     override fun updateComponent(component: Component): Boolean {
         if (component !is Image || componentId != component.componentId) return false
 
-        component.imageData?.let {
-            imageData = component.imageData
-            updateImageHash()
-        }
-
-        contentScale = component.contentScale
-        colorFilter = component.colorFilter
+        withSafeMultiLock(component) { performUpdate(component) }
 
         return true
     }
 
+    private fun performUpdate(other: Image) {
+        contentScale = other.contentScale
+        colorFilter = other.colorFilter
+
+        if (other.imageData != null) {
+            imageData = other.imageData
+            imageHash = other.imageHash
+            capturedGenerationId = other.capturedGenerationId
+            compressedData = other.compressedData
+            cachedHashCode = other.cachedHashCode
+        } else {
+            cachedHashCode = null
+        }
+    }
+
+    /**
+     * Note: This method compares the properties of the [Image] component, including a snapshot of
+     * the [Bitmap] content taken at construction time. If the underlying [Bitmap] is mutated in
+     * place after construction, this instance will still be considered equal to other [Image]
+     * instances created from the same [Bitmap] state. To ensure UI updates after a [Bitmap]
+     * mutation, a new [Image] instance should be created or the existing one should be updated via
+     * [updateComponent].
+     */
     override fun equals(other: Any?): Boolean {
         if (other === this) return true
-
         if (other !is Image) return false
+        if (!super.equals(other)) return false
 
-        val imageEquals =
-            imageHashString?.let { it == other.imageHashString } ?: (other.imageHashString == null)
-        return imageEquals &&
-            super.equals(other) &&
-            contentScale == other.contentScale &&
-            colorFilter == other.colorFilter
+        return withSafeMultiLock(other) { equalsInternal(other) }
+    }
+
+    private fun equalsInternal(other: Image): Boolean {
+        if (contentScale != other.contentScale || colorFilter != other.colorFilter) {
+            return false
+        }
+
+        if (imageData === other.imageData && capturedGenerationId == other.capturedGenerationId) {
+            return true
+        }
+
+        return Arrays.equals(imageHash, other.imageHash)
+    }
+
+    private inline fun <T> withSafeMultiLock(other: Image, block: () -> T): T {
+        val h1 = System.identityHashCode(this.lock)
+        val h2 = System.identityHashCode(other.lock)
+
+        return when {
+            h1 < h2 -> synchronized(this.lock) { synchronized(other.lock) { block() } }
+            h1 > h2 -> synchronized(other.lock) { synchronized(this.lock) { block() } }
+            else ->
+                synchronized(TIE_LOCK) {
+                    synchronized(this.lock) { synchronized(other.lock) { block() } }
+                }
+        }
     }
 
     override fun hashCode(): Int {
-        var result = super.hashCode()
-        result = 31 * result + contentScale.hashCode()
-        result = 31 * result + colorFilter.hashCode()
-        result = 31 * result + (imageData?.hashCode() ?: 0)
-        return result
+        var cached = cachedHashCode
+        if (cached != null) return cached
+
+        synchronized(lock) {
+            cached = cachedHashCode
+            if (cached != null) return cached
+
+            val currentContentScale = contentScale
+            val currentColorFilter = colorFilter
+            val currentImageHash = imageHash
+
+            var result = super.hashCode()
+            result = 31 * result + currentContentScale.hashCode()
+            result = 31 * result + currentColorFilter.hashCode()
+            result = 31 * result + Arrays.hashCode(currentImageHash)
+            cached = result
+            cachedHashCode = cached
+            return cached
+        }
     }
 
-    private fun updateImageHash() {
-        val md = MessageDigest.getInstance(HASH_ALGORITHM)
-        val imageByteArray = imageData?.let { toByteArray(it) }
-        val hashBytes = imageByteArray?.let { md.digest(it) }
-        imageHashString = hashBytes?.joinToString { HEX_FORMAT.format(it) }
+    private fun updateImageHashAndCache() {
+        synchronized(lock) {
+            val bitmap = imageData ?: return
+            capturedGenerationId = bitmap.generationId
+            val md = MessageDigest.getInstance(HASH_ALGORITHM)
+            val byteBuffer = ByteBuffer.allocate(bitmap.byteCount)
+            bitmap.copyPixelsToBuffer(byteBuffer)
+            imageHash = md.digest(byteBuffer.array())
+            compressedData = null
+            cachedHashCode = null
+        }
+    }
+
+    private fun getCompressedData(): ByteArray? {
+        var result = compressedData
+        if (result == null) {
+            synchronized(lock) {
+                result = compressedData
+                if (result == null) {
+                    val currentImageData = imageData
+                    result = toByteArray(currentImageData)
+                    compressedData = result
+                }
+            }
+        }
+        return result
     }
 
     /**
@@ -201,8 +286,8 @@
         private const val TAG = "Image"
         private const val BITMAP_QUALITY = 100
         private const val BITMAP_OFFSET = 0
-        private const val HASH_ALGORITHM = "SHA-512"
-        private const val HEX_FORMAT = "%02x"
+        private const val HASH_ALGORITHM = "MD5"
+        private val TIE_LOCK = Any()
 
         /** @return an instance of [Builder] */
         @JvmStatic fun newBuilder(componentId: String) = Builder(componentId)
diff --git a/car-apps-common/res/color/app_bar_background_color.xml b/car-apps-common/res/color/app_bar_background_color.xml
new file mode 100644
index 0000000..6d6744f
--- /dev/null
+++ b/car-apps-common/res/color/app_bar_background_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.88" />
+</selector>
diff --git a/car-apps-common/res/color/background_image_scrim_30pc_bg_color.xml b/car-apps-common/res/color/background_image_scrim_30pc_bg_color.xml
new file mode 100644
index 0000000..6729456
--- /dev/null
+++ b/car-apps-common/res/color/background_image_scrim_30pc_bg_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.30" />
+</selector>
diff --git a/car-apps-common/res/color/background_image_scrim_50pc_bg_color.xml b/car-apps-common/res/color/background_image_scrim_50pc_bg_color.xml
new file mode 100644
index 0000000..4fe6b31
--- /dev/null
+++ b/car-apps-common/res/color/background_image_scrim_50pc_bg_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.50" />
+</selector>
diff --git a/car-apps-common/res/color/background_image_scrim_70pc_bg_color.xml b/car-apps-common/res/color/background_image_scrim_70pc_bg_color.xml
new file mode 100644
index 0000000..6a0c0cb
--- /dev/null
+++ b/car-apps-common/res/color/background_image_scrim_70pc_bg_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.70" />
+</selector>
diff --git a/car-apps-common/res/color/background_image_scrim_80pc_bg_color.xml b/car-apps-common/res/color/background_image_scrim_80pc_bg_color.xml
new file mode 100644
index 0000000..f54b13d
--- /dev/null
+++ b/car-apps-common/res/color/background_image_scrim_80pc_bg_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.80" />
+</selector>
diff --git a/car-apps-common/res/color/background_image_scrim_96pc_bg_color.xml b/car-apps-common/res/color/background_image_scrim_96pc_bg_color.xml
new file mode 100644
index 0000000..79cead4
--- /dev/null
+++ b/car-apps-common/res/color/background_image_scrim_96pc_bg_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.96" />
+</selector>
diff --git a/car-apps-common/res/color/car_card_ripple_background.xml b/car-apps-common/res/color/car_card_ripple_background.xml
new file mode 100644
index 0000000..5d1ba12
--- /dev/null
+++ b/car-apps-common/res/color/car_card_ripple_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground" android:alpha="0.09" />
+</selector>
diff --git a/car-apps-common/res/color/car_tab_selected_color.xml b/car-apps-common/res/color/car_tab_selected_color.xml
new file mode 100644
index 0000000..c4c8780
--- /dev/null
+++ b/car-apps-common/res/color/car_tab_selected_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground" />
+</selector>
diff --git a/car-apps-common/res/color/car_tab_unselected_color.xml b/car-apps-common/res/color/car_tab_unselected_color.xml
new file mode 100644
index 0000000..b0c6e1f
--- /dev/null
+++ b/car-apps-common/res/color/car_tab_unselected_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground" android:alpha="0.50" />
+</selector>
diff --git a/car-apps-common/res/color/control_bar_button_background_color.xml b/car-apps-common/res/color/control_bar_button_background_color.xml
new file mode 100644
index 0000000..52f29a9
--- /dev/null
+++ b/car-apps-common/res/color/control_bar_button_background_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground" android:alpha="0.40" />
+</selector>
diff --git a/car-apps-common/res/color/primary_app_icon_color.xml b/car-apps-common/res/color/primary_app_icon_color.xml
new file mode 100644
index 0000000..c4c8780
--- /dev/null
+++ b/car-apps-common/res/color/primary_app_icon_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground" />
+</selector>
diff --git a/car-apps-common/res/color/scrim_overlay_color.xml b/car-apps-common/res/color/scrim_overlay_color.xml
new file mode 100644
index 0000000..923d57e
--- /dev/null
+++ b/car-apps-common/res/color/scrim_overlay_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackground" android:alpha="0.78" />
+</selector>
diff --git a/car-apps-common/res/color/secondary_app_icon_color.xml b/car-apps-common/res/color/secondary_app_icon_color.xml
new file mode 100644
index 0000000..9dfa255
--- /dev/null
+++ b/car-apps-common/res/color/secondary_app_icon_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2026 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorForeground" android:alpha="0.72" />
+</selector>
diff --git a/car-apps-common/res/color/selectable_button_tint_selector.xml b/car-apps-common/res/color/selectable_button_tint_selector.xml
index c0c387d..fd20c19 100644
--- a/car-apps-common/res/color/selectable_button_tint_selector.xml
+++ b/car-apps-common/res/color/selectable_button_tint_selector.xml
@@ -15,6 +15,6 @@
   limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="true" android:color="#000000"/>
-    <item android:state_selected="false" android:color="@color/primary_app_icon_color"/>
+    <item android:state_selected="true" android:color="?android:attr/colorBackground"/>
+    <item android:state_selected="false" android:color="?android:attr/colorForeground"/>
 </selector>
diff --git a/car-apps-common/res/color/uxr_button_image_color_selector.xml b/car-apps-common/res/color/uxr_button_image_color_selector.xml
index 6f8e9ba..8ce2612 100644
--- a/car-apps-common/res/color/uxr_button_image_color_selector.xml
+++ b/car-apps-common/res/color/uxr_button_image_color_selector.xml
@@ -17,6 +17,6 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:app="http://schemas.android.com/apk/res-auto">
-    <item app:state_ux_restricted="true" android:color="@color/uxr_button_image_disabled_color"/>
-    <item app:state_ux_restricted="false" android:color="@color/uxr_button_image_color"/>
+    <item app:state_ux_restricted="true" android:color="?android:attr/colorForeground" android:alpha="0.50"/>
+    <item app:state_ux_restricted="false" android:color="?android:attr/colorForeground"/>
 </selector>
diff --git a/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml b/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml
index 9035a65..fc0c882 100644
--- a/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml
+++ b/car-apps-common/res/drawable-ldrtl/background_image_scrim.xml
@@ -20,9 +20,9 @@
         <shape>
             <gradient
                 android:angle="270"
-                android:startColor="#F5000000"
+                android:startColor="@color/background_image_scrim_96pc_bg_color"
                 android:centerColor="@android:color/transparent"
-                android:endColor="#F5000000"/>
+                android:endColor="@color/background_image_scrim_96pc_bg_color"/>
         </shape>
     </item>
     <item>
@@ -31,8 +31,8 @@
                 android:angle="180"
                 android:centerX="0.52"
                 android:startColor="@android:color/transparent"
-                android:centerColor="@android:color/black"
-                android:endColor="@android:color/black" />
+                android:centerColor="?android:attr/colorBackground"
+                android:endColor="?android:attr/colorBackground" />
         </shape>
     </item>
     <item>
@@ -41,13 +41,13 @@
                 android:angle="180"
                 android:centerX="0.62"
                 android:startColor="@android:color/transparent"
-                android:centerColor="#B3000000"
-                android:endColor="#B3000000" />
+                android:centerColor="@color/background_image_scrim_70pc_bg_color"
+                android:endColor="@color/background_image_scrim_70pc_bg_color" />
         </shape>
     </item>
     <item>
         <shape>
-            <solid android:color="@color/background_image_30p_black"/>
+            <solid android:color="@color/background_image_scrim_30pc_bg_color"/>
         </shape>
     </item>
 </layer-list>
diff --git a/car-apps-common/res/drawable-port/background_image_scrim.xml b/car-apps-common/res/drawable-port/background_image_scrim.xml
index 3e3437f..34b6f14 100644
--- a/car-apps-common/res/drawable-port/background_image_scrim.xml
+++ b/car-apps-common/res/drawable-port/background_image_scrim.xml
@@ -21,8 +21,8 @@
             <gradient
                 android:angle="90"
                 android:centerY="0.3"
-                android:startColor="@android:color/black"
-                android:centerColor="@android:color/black"
+                android:startColor="?android:attr/colorBackground"
+                android:centerColor="?android:attr/colorBackground"
                 android:endColor="@android:color/transparent"/>
         </shape>
     </item>
@@ -31,17 +31,18 @@
             <gradient
                 android:angle="90"
                 android:centerY="0.48"
-                android:startColor="#80000000"
-                android:centerColor="#80000000"
+                android:startColor="#FFFF0000"
+                android:centerColor="#FFFF0000"
                 android:endColor="@android:color/transparent"/>
         </shape>
+        <!-- @color/background_image_scrim_50pc_bg_color-->
     </item>
     <item>
         <shape>
             <gradient
                 android:angle="270"
                 android:centerY="0.64"
-                android:startColor="#CC000000"
+                android:startColor="@color/background_image_scrim_80pc_bg_color"
                 android:centerColor="@android:color/transparent"/>
         </shape>
     </item>
diff --git a/car-apps-common/res/drawable/background_image_scrim.xml b/car-apps-common/res/drawable/background_image_scrim.xml
index 89a8092..db55043 100644
--- a/car-apps-common/res/drawable/background_image_scrim.xml
+++ b/car-apps-common/res/drawable/background_image_scrim.xml
@@ -20,9 +20,9 @@
         <shape>
             <gradient
                 android:angle="90"
-                android:startColor="#F5000000"
+                android:startColor="@color/background_image_scrim_96pc_bg_color"
                 android:centerColor="@android:color/transparent"
-                android:endColor="#F5000000"/>
+                android:endColor="@color/background_image_scrim_96pc_bg_color"/>
         </shape>
     </item>
     <item>
@@ -31,8 +31,8 @@
                 android:angle="0"
                 android:centerX="0.48"
                 android:startColor="@android:color/transparent"
-                android:centerColor="@android:color/black"
-                android:endColor="@android:color/black" />
+                android:centerColor="?android:attr/colorBackground"
+                android:endColor="?android:attr/colorBackground" />
         </shape>
     </item>
     <item>
@@ -41,13 +41,14 @@
                 android:angle="0"
                 android:centerX="0.38"
                 android:startColor="@android:color/transparent"
-                android:centerColor="#B3000000"
-                android:endColor="#B3000000" />
+                android:centerColor="@color/background_image_scrim_70pc_bg_color"
+                android:endColor="@color/background_image_scrim_70pc_bg_color" />
         </shape>
+        <!-- -->
     </item>
     <item>
         <shape>
-            <solid android:color="@color/background_image_30p_black"/>
+            <solid android:color="@color/background_image_scrim_30pc_bg_color"/>
         </shape>
     </item>
 </layer-list>
diff --git a/car-apps-common/res/layout-port/background_image.xml b/car-apps-common/res/layout-port/background_image.xml
index 7e4ee8e..dffbcd2 100644
--- a/car-apps-common/res/layout-port/background_image.xml
+++ b/car-apps-common/res/layout-port/background_image.xml
@@ -41,7 +41,7 @@
         android:id="@+id/background_image_darkening_scrim"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@color/background_image_30p_black"
+        android:background="@color/background_image_scrim_30pc_bg_color"
         android:visibility="gone"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
diff --git a/car-apps-common/res/values-de/strings.xml b/car-apps-common/res/values-de/strings.xml
index 025a447..631b09b 100644
--- a/car-apps-common/res/values-de/strings.xml
+++ b/car-apps-common/res/values-de/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="control_bar_expand_collapse_button" msgid="3420351169078117938">"Schaltfläche zum Maximieren/Minimieren"</string>
+    <string name="control_bar_expand_collapse_button" msgid="3420351169078117938">"Button zum Maximieren/Minimieren"</string>
     <string name="car_drawer_open" msgid="2676372472514742324">"Leiste öffnen"</string>
     <string name="car_drawer_close" msgid="5329374630462464855">"Leiste schließen"</string>
     <string name="restricted_while_driving" msgid="2278031053760704437">"Funktion während der Fahrt nicht verfügbar."</string>
diff --git a/car-apps-common/res/values-night/colors.xml b/car-apps-common/res/values-night/colors.xml
deleted file mode 100644
index d00832e..0000000
--- a/car-apps-common/res/values-night/colors.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2019 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<resources>
-    <color name="car_tab_selected_color">@color/car_tab_selected_color_dark</color>
-    <color name="car_tab_unselected_color">@color/car_tab_unselected_color_dark</color>
-    <color name="scrim_overlay_color">#D6000000</color>
-
-    <color name="primary_app_icon_color">#E0FFFFFF</color>
-    <color name="secondary_app_icon_color">#99FFFFFF</color>
-
-    <color name="app_bar_background_color">#EB000000</color>
-</resources>
diff --git a/car-apps-common/res/values/colors.xml b/car-apps-common/res/values/colors.xml
index ddac704..22e323a 100644
--- a/car-apps-common/res/values/colors.xml
+++ b/car-apps-common/res/values/colors.xml
@@ -38,27 +38,9 @@
     <color name="improper_image_refs_tint_color">#C8FF0000</color>
 
     <color name="control_bar_background_color">@android:color/transparent</color>
-    <color name="scrim_overlay_color">#C7000000</color>
-    <color name="app_bar_background_color">#E0000000</color>
-
-    <color name="car_tab_selected_color">@color/car_tab_selected_color_light</color>
-    <color name="car_tab_selected_color_dark">#E2FFFFFF</color>
-    <color name="car_tab_selected_color_light">#FFFFFFFF</color>
-    <color name="car_tab_unselected_color">@color/car_tab_unselected_color_light</color>
-    <color name="car_tab_unselected_color_dark">#80FFFFFF</color>
-    <color name="car_tab_unselected_color_light">#90FFFFFF</color>
-
-    <color name="primary_app_icon_color">#FFFFFFFF</color>
-    <color name="secondary_app_icon_color">#B8FFFFFF</color>
-    <color name="car_card_ripple_background">#17000000</color>
 
     <color name="background_image_30p_black">#4D000000</color>
 
-    <color name="uxr_button_image_color">@color/primary_app_icon_color</color>
-    <color name="uxr_button_image_disabled_color">#80FFFFFF</color>
-
-    <color name="control_bar_button_background_color">#66ffffff</color>
-
     <color name="hero_button_background_color">@color/car_grey_868</color>
     <color name="hero_button_text_color">@color/primary_text_color</color>
 
@@ -67,7 +49,6 @@
     <color name="car_seekbar_background_color">#404659</color>
     <color name="car_seekbar_icon_color">#002B76</color>
 
-
     <!--
         Color palette for cars.
         Those values are NOT part of the car-ui-lib "resource API", they are just constants used in
@@ -99,5 +80,5 @@
     <color name="car_red_500a">#ffd50000</color>
 
     <!-- End color palette -->
-
 </resources>
+
diff --git a/car-apps-common/res/values/overlayable.xml b/car-apps-common/res/values/overlayable.xml
index 3e5c656..2a47347 100644
--- a/car-apps-common/res/values/overlayable.xml
+++ b/car-apps-common/res/values/overlayable.xml
@@ -16,6 +16,12 @@
       <item type="bool" name="use_media_source_color_for_minimized_progress_bar"/>
 
       <item type="color" name="action_button_icon_tint" />
+      <item type="color" name="background_image_scrim_30pc_bg_color" />
+      <item type="color" name="background_image_scrim_50pc_bg_color" />
+      <item type="color" name="background_image_scrim_70pc_bg_color" />
+      <item type="color" name="background_image_scrim_80pc_bg_color" />
+      <item type="color" name="background_image_scrim_96pc_bg_color" />
+      <item type="color" name="control_bar_button_background_color" />
 
       <item type="dimen" name="control_bar_button_size" />
       <item type="dimen" name="control_bar_button_padding" />
diff --git a/car-apps-common/src/com/android/car/apps/common/ControlBar.java b/car-apps-common/src/com/android/car/apps/common/ControlBar.java
index e167cd5..4940727 100644
--- a/car-apps-common/src/com/android/car/apps/common/ControlBar.java
+++ b/car-apps-common/src/com/android/car/apps/common/ControlBar.java
@@ -102,6 +102,9 @@
     // Weight for the spacers used between buttons
     private static final float SPACERS_WEIGHT = 1f;
 
+    // Delay before closing the control bar when it becomes empty while expanded.
+    private static final long CLOSE_IF_EMPTY_DELAY_MS = 100;
+
     private final OnGlobalFocusChangeListener mFocusChangeListener =
             (oldFocus, newFocus) -> {
                 // Collapse the control bar when it is expanded and loses focus.
@@ -112,7 +115,6 @@
                 mHasFocus = hasFocus;
             };
 
-
     public ControlBar(Context context) {
         super(context);
         init(context, null, 0, 0);
@@ -344,14 +346,22 @@
         // mRowsContainer's children are in reverse order (last row is at index 0)
         // When changing source (b/381304903), when the number of extra rows is less than before,
         // all rows except the main row should be hidden. When the number of rows is greater than
-        // before, only the main row should be set visible
+        // before, the main row should be set visible, and the extra rows should be set to visible
+        // if mIsExpanded is true.
         if (numExtraRowsInUseBefore > mNumExtraRowsInUse) {
-            for (int i = 0; i < mRowsContainer.getChildCount() - 1; i++) {
+            for (int i = mNumExtraRowsInUse; i < mRowsContainer.getChildCount() - 1; i++) {
                 mRowsContainer.getChildAt(i).setVisibility(View.GONE);
             }
         } else if (numExtraRowsInUseBefore < mNumExtraRowsInUse) {
             mRowsContainer.getChildAt(mRowsContainer.getChildCount() - 1)
                     .setVisibility(View.VISIBLE);
+            for (int i = numExtraRowsInUseBefore; i < mNumExtraRowsInUse; i++) {
+                mRowsContainer.getChildAt(i).setVisibility(mIsExpanded ? View.VISIBLE : View.GONE);
+            }
+        }
+
+        if (mIsExpanded && mNumExtraRowsInUse == 0) {
+            close();
         }
     }
 
diff --git a/car-media-common/res/drawable/ic_placeholder_tintable.xml b/car-media-common/res/drawable/ic_placeholder_tintable.xml
index cac71dd..1faefff 100644
--- a/car-media-common/res/drawable/ic_placeholder_tintable.xml
+++ b/car-media-common/res/drawable/ic_placeholder_tintable.xml
@@ -19,7 +19,7 @@
     android:width="48dp"
     android:viewportHeight="103"
     android:viewportWidth="103">
-    <path android:fillColor="#FFF" android:fillType="evenOdd"
+    <path android:fillColor="?android:attr/colorForeground" android:fillType="evenOdd"
         android:pathData="M52,34.5L52,53.842C50.918,53.218 49.672,52.833 48.333,52.833C44.282,52.833 41,56.115 41,60.167C41,64.218 44.282,67.5 48.333,67.5C52.385,67.5 55.667,64.218 55.667,60.167L55.667,41.833L63,41.833L63,34.5L52,34.5Z"
-        android:strokeColor="#FFF" android:strokeWidth="1"/>
+        android:strokeColor="?android:attr/colorForeground" android:strokeWidth="1"/>
 </vector>
diff --git a/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java b/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java
index 85c776c..ca469a4 100644
--- a/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java
+++ b/car-media-common/src/com/android/car/media/common/CustomPlaybackAction.java
@@ -26,9 +26,6 @@
 
 import com.android.car.media.common.playback.PlaybackViewModel.PlaybackStateWrapper;
 
-import java.util.Objects;
-
-
 /**
  * Abstract representation of a custom playback action. A custom playback action represents a
  * visual element that can be used to trigger playback actions not included in the standard
@@ -52,10 +49,14 @@
     /**
      * Creates a custom action
      */
+    @Nullable
     public static CustomPlaybackAction create(@NonNull Context context, @NonNull String action,
             @Nullable Bundle extras, @NonNull IconCompat iconCompat) {
-        return new CustomPlaybackAction(Objects.requireNonNull(iconCompat.loadDrawable(context)),
-                action, extras, iconCompat);
+        Drawable drawable = iconCompat.loadDrawable(context);
+        if (drawable == null) {
+            return null;
+        }
+        return new CustomPlaybackAction(drawable, action, extras, iconCompat);
     }
 
     private CustomPlaybackAction(
diff --git a/car-media-common/src/com/android/car/media/common/MediaButtonController.java b/car-media-common/src/com/android/car/media/common/MediaButtonController.java
index 4abc3f5..3484baf 100644
--- a/car-media-common/src/com/android/car/media/common/MediaButtonController.java
+++ b/car-media-common/src/com/android/car/media/common/MediaButtonController.java
@@ -44,6 +44,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -266,6 +267,7 @@
             imageButtons.addAll(state.getCustomActions()
                     .stream()
                     .map(rawAction -> rawAction.fetchDrawable(mContext))
+                    .filter(Objects::nonNull)
                     .map(action -> getOrCreateIconButton(action))
                     .collect(Collectors.toList()));
         }
diff --git a/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java b/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java
index 075e602..b59279c 100644
--- a/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java
+++ b/car-media-common/src/com/android/car/media/common/MediaItemMetadata.java
@@ -445,6 +445,14 @@
         }
     }
 
+    /**
+     * Clears the static cache of placeholder drawables. This should be called
+     * when the application's theme or configuration changes.
+     */
+    public static void clearPlaceholderCache() {
+        sPlaceHolders.clear();
+    }
+
     private static List<Drawable> getPlaceHolders(PlaceholderType type, Context context) {
         List<Drawable> placeHolders = sPlaceHolders.get(type);
         if (placeHolders == null) {
@@ -457,7 +465,11 @@
 
             placeHolders = new ArrayList<>(placeholderImages.length());
             for (int i = 0; i < placeholderImages.length(); i++) {
-                placeHolders.add(placeholderImages.getDrawable(i));
+                int resId = placeholderImages.getResourceId(i, 0);
+                if (resId != 0) {
+                    // Use the context to get proper theming.
+                    placeHolders.add(context.getDrawable(resId));
+                }
             }
             placeholderImages.recycle();
             sPlaceHolders.put(type, placeHolders);
diff --git a/car-media-common/src/com/android/car/media/common/MediaLinkHandler.java b/car-media-common/src/com/android/car/media/common/MediaLinkHandler.java
index 1de725a..25743c6 100644
--- a/car-media-common/src/com/android/car/media/common/MediaLinkHandler.java
+++ b/car-media-common/src/com/android/car/media/common/MediaLinkHandler.java
@@ -61,6 +61,7 @@
         if (TextUtils.isEmpty(mLinkedMediaId) || (mControllerDelegate == null)
                 || (mMediaItemsRepository == null)) {
             mDisplayView.setOnClickListener(null);
+            mDisplayView.setClickable(false); // setOnClickListener makes the view clickable...
         } else {
             mDisplayView.setOnClickListener(view -> mMediaItemsRepository.getItem(mLinkedMediaId,
                     new MediaBrowserCompat.ItemCallback() {
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSessionHelper.java b/car-media-common/src/com/android/car/media/common/source/MediaSessionHelper.java
index 69d995f..3e5208a 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSessionHelper.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSessionHelper.java
@@ -423,7 +423,7 @@
                 return;
             }
             mActiveOrPausedMediaSources
-                .setValue(mInputFactory.getMediaSources(activeMediaControllers));
+                    .setValue(mInputFactory.getMediaSources(activeMediaControllers));
         }
     }
 
@@ -435,34 +435,73 @@
 
         parseMediaControllers(filteredControllers,
                 activeMediaControllers, activeOrPausedMediaControllers);
-        MediaSource savedMediaSource = null;
 
         // Setup initial activeMediaController
         if (activeMediaControllers.isEmpty()) {
             // Get the last saved media source
-            String savedMediaSourceName = getLastActiveMediaSource();
-            if (TextUtils.isEmpty(savedMediaSourceName)) {
-                // Don't change default values
-                return;
+            String savedMediaSourceName = mSharedPrefs.getString(LAST_ACTIVE_MEDIA_SOURCE, "");
+            if (!TextUtils.isEmpty(savedMediaSourceName)) {
+                setSavedMediaSource(savedMediaSourceName, activeOrPausedMediaControllers);
+            } else {
+                getCarMediaServiceSessionAsync(activeOrPausedMediaControllers);
             }
-            savedMediaSource = createSavedMediaSource(savedMediaSourceName,
-                    activeOrPausedMediaControllers);
-            savedMediaSource = maybeReplacePrimaryMediaSource(savedMediaSource);
-            mPrimaryMediaSource.setValue(savedMediaSource);
         } else {
             updatePrimaryMediaSource(activeMediaControllers);
         }
 
         // Setup initial activeOrPausedMediaSources
+        if (!activeOrPausedMediaControllers.isEmpty()) {
+            updateActiveOrPausedMediaSources(activeOrPausedMediaControllers);
+        }
+    }
+
+    private void setSavedMediaSource(String savedMediaSourceName,
+            List<MediaController> activeOrPausedMediaControllers) {
+        MediaSource savedMediaSource = createSavedMediaSource(savedMediaSourceName,
+                activeOrPausedMediaControllers);
+        savedMediaSource = maybeReplacePrimaryMediaSource(savedMediaSource);
+        mPrimaryMediaSource.setValue(savedMediaSource);
+
         if (activeOrPausedMediaControllers.isEmpty()) {
             if (savedMediaSource != null) {
                 mActiveOrPausedMediaSources.setValue(Collections.singletonList(savedMediaSource));
             }
-        } else {
-            updateActiveOrPausedMediaSources(activeOrPausedMediaControllers);
         }
     }
 
+    private void getCarMediaServiceSessionAsync(
+            List<MediaController> activeOrPausedMediaControllers) {
+        Context context = mContext.get();
+        if (context == null) {
+            return;
+        }
+
+        Car.createCar(context, null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, (car, ready) -> {
+            if (!ready) {
+                return;
+            }
+            try {
+                CarMediaManager carMediaManager =
+                        (CarMediaManager) car.getCarManager(Car.CAR_MEDIA_SERVICE);
+                if (carMediaManager != null) {
+                    ComponentName componentName = carMediaManager.getMediaSource(
+                            MEDIA_SOURCE_MODE_PLAYBACK);
+                    if (componentName != null) {
+                        setSavedMediaSource(componentName.flattenToString(),
+                                activeOrPausedMediaControllers);
+                    }
+                }
+            } catch (SecurityException e) {
+                Log.e(TAG, "Unable to read CarMediaManager media source. Requires "
+                        + "android.permission.MEDIA_CONTENT_CONTROL " + e);
+            } finally {
+                if (car != null) {
+                    car.disconnect();
+                }
+            }
+        });
+    }
+
     private MediaSource createSavedMediaSource(String savedMediaSourceName,
             List<MediaController> activeOrPausedControllers) {
         String packageName = savedMediaSourceName;
@@ -538,31 +577,7 @@
         }
     }
 
-    private String getLastActiveMediaSource() {
-        String mediaSource = mSharedPrefs.getString(LAST_ACTIVE_MEDIA_SOURCE, "");
 
-        return TextUtils.isEmpty(mediaSource)
-                ? getCarMediaServiceSession() : mediaSource;
-    }
-
-    private String getCarMediaServiceSession() {
-        Car car = Car.createCar(mContext.get());
-        ComponentName componentName = null;
-        if (car != null) {
-            CarMediaManager carMediaManager =
-                    (CarMediaManager) car.getCarManager(Car.CAR_MEDIA_SERVICE);
-            try {
-                componentName = carMediaManager.getMediaSource(MEDIA_SOURCE_MODE_PLAYBACK);
-            } catch (SecurityException e) {
-                Log.e(TAG, "Unable to read CarMediaManager media source. Requires "
-                        + "android.permission.MEDIA_CONTENT_CONTROL " + e);
-            }
-            car.disconnect();
-        }
-
-        // ComponentName may be null b/355078140
-        return componentName == null ? "" : componentName.flattenToString();
-    }
 
     /* Copy of PlaybackState.isActive() which is only available for minsdk >=S  */
     private boolean isActive(int playbackState) {
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSource.java b/car-media-common/src/com/android/car/media/common/source/MediaSource.java
index cb4461b..398f9a1 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSource.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSource.java
@@ -328,12 +328,16 @@
             Log.e(TAG, "getServiceFromExtras null controller");
             return null;
         }
-        Bundle extras = controller.getExtras();
-        if (extras == null || extras.getString(Car.CAR_EXTRA_BROWSE_SERVICE_FOR_SESSION) == null) {
+
+        final Bundle extras = controller.getExtras();
+        if (extras == null) {
             return null;
         }
-        String serviceNameString =
-                controller.getExtras().getString(Car.CAR_EXTRA_BROWSE_SERVICE_FOR_SESSION);
+
+        final String serviceNameString = extras.getString(Car.CAR_EXTRA_BROWSE_SERVICE_FOR_SESSION);
+        if (serviceNameString == null) {
+            return null;
+        }
 
         return new ComponentName(controller.getPackageName(), serviceNameString);
     }
@@ -395,6 +399,15 @@
     }
 
     /**
+     * @return the {@link ComponentName} of the ignored browse service, if it was created with
+     * ignoreBrowser=true.
+     */
+    @Nullable
+    public ComponentName getIgnoredBrowseServiceComponentName() {
+        return mIgnoredBrowseService;
+    }
+
+    /**
      * @return a {@link Drawable} as the media source's icon.
      */
     @NonNull
diff --git a/car-media-common/tests/unittests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java b/car-media-common/tests/unittests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
index 5f7b664..5619c94 100644
--- a/car-media-common/tests/unittests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
+++ b/car-media-common/tests/unittests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
@@ -40,6 +40,7 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
+import com.android.car.media.common.CustomPlaybackAction;
 import com.android.car.media.common.MediaItemMetadata;
 import com.android.car.media.common.source.MediaBrowserConnector.BrowsingState;
 import com.android.car.media.common.source.MediaBrowserConnector.ConnectionStatus;
@@ -298,6 +299,17 @@
         deliverValuesToCallbacks(newCallbackCaptor, newMetadata, newPlaybackState);
     }
 
+    @Test
+    public void testRawCustomPlaybackAction_fetchDrawable_invalidResource_returnsNull() {
+        int nonDrawableResourceId = android.R.string.ok;
+        PlaybackViewModel.RawCustomPlaybackAction rawAction =
+                new PlaybackViewModel.RawCustomPlaybackAction(
+                        nonDrawableResourceId, null, "action", null);
+
+        CustomPlaybackAction action = rawAction.fetchDrawable(mContext);
+        assertThat(action).isNull();
+    }
+
     private void deliverValuesToCallbacks(
             ArgumentCaptor<MediaControllerCompat.Callback> callbackCaptor,
             MediaMetadataCompat metadata,
diff --git a/car-ui-lib/aaos-studio/AndroidManifest.xml b/car-ui-lib/aaos-studio/AndroidManifest.xml
index 23a6244..e9b3ad2 100644
--- a/car-ui-lib/aaos-studio/AndroidManifest.xml
+++ b/car-ui-lib/aaos-studio/AndroidManifest.xml
@@ -32,6 +32,10 @@
 
     <uses-library android:name="com.android.oem.tokens" android:required="false"/>
 
+    <provider android:name=".TokenProvider"
+              android:authorities="com.android.aaos.studio.provider"
+              android:exported="true" />
+
     <activity
         android:name=".TokenActivity"
         android:exported="true">
diff --git a/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenActivity.java b/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenActivity.java
index c88c2da..049b7f6 100644
--- a/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenActivity.java
+++ b/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenActivity.java
@@ -23,9 +23,10 @@
 import android.graphics.Color;
 import android.graphics.drawable.GradientDrawable;
 import android.os.Bundle;
-import android.util.Pair;
 import android.util.TypedValue;
 import android.view.View;
+import android.widget.EditText;
+import android.widget.RadioButton;
 import android.widget.SeekBar;
 import android.widget.Switch;
 import android.widget.Toast;
@@ -39,12 +40,21 @@
 import com.android.car.ui.toolbar.ToolbarController;
 
 import com.google.ux.material.libmonet.blend.Blend;
+import com.google.ux.material.libmonet.dynamiccolor.DynamicScheme;
 import com.google.ux.material.libmonet.hct.Hct;
+import com.google.ux.material.libmonet.palettes.TonalPalette;
+import com.google.ux.material.libmonet.scheme.SchemeContent;
+import com.google.ux.material.libmonet.scheme.SchemeExpressive;
+import com.google.ux.material.libmonet.scheme.SchemeNeutral;
+import com.google.ux.material.libmonet.scheme.SchemeTonalSpot;
 import com.google.ux.material.libmonet.scheme.SchemeVibrant;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
+
 
 /**
  * Activity that shows displays the values of OEM design tokens.
@@ -58,10 +68,14 @@
 
     private OverlayManager mOverlayManager;
     private View mColorPreview;
-    private SchemeVibrant mScheme;
+    private DynamicScheme mScheme;
     private boolean mIsLightMode;
     private boolean mSquareCorners;
     private SeekBar mSeekBar;
+    private EditText mHexInput;
+    private String mSchemeType = "Vibrant";
+    private float mSaturation = 1.0f;
+    private float mValue = 1.0f;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -111,30 +125,106 @@
         Switch cornerSwitch = requireViewById(R.id.corner_switch);
         mColorPreview = requireViewById(R.id.color_preview);
         mSeekBar = requireViewById(R.id.color_seekbar);
+        mHexInput = requireViewById(R.id.hex_input);
+        mHexInput.setOnEditorActionListener((v, actionId, event) -> {
+            String text = v.getText().toString();
+            if (text.matches("^#?([0-9a-fA-F]{6})$")) {
+                int color = Color.parseColor(text.startsWith("#") ? text : "#" + text);
+                float[] hsv = new float[3];
+                Color.colorToHSV(color, hsv);
+                mSeekBar.setProgress((int) hsv[0]);
+                mSaturation = hsv[1];
+                mValue = hsv[2];
+                updateColorPreview();
+            } else {
+                Toast.makeText(this, "Invalid hex color", Toast.LENGTH_SHORT).show();
+                mSeekBar.setProgress(0);
+                mSaturation = 1.0f;
+                mValue = 1.0f;
+                updateColorPreview();
+            }
+            return false;
+        });
 
         mIsLightMode = isLightMode(Token.getColor(this, R.attr.oemColorSurface),
                 Token.getColor(this, R.attr.oemColorOnSurface));
-        lightSwitch.setChecked(mIsLightMode);
-        lightSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> mIsLightMode = isChecked);
+        lightSwitch.setChecked(!mIsLightMode);
+        lightSwitch.setOnCheckedChangeListener(
+                (buttonView, isChecked) -> mIsLightMode = !isChecked);
 
         mSquareCorners = Token.getCornerRadius(this, R.attr.oemShapeCornerFull) == 0;
         cornerSwitch.setChecked(mSquareCorners);
         cornerSwitch.setOnCheckedChangeListener(
                 (buttonView, isChecked) -> mSquareCorners = isChecked);
 
+        List<RadioButton> radioButtons = new ArrayList<>();
+        RadioButton rbTonalSpot = requireViewById(R.id.scheme_tonal_spot);
+        RadioButton rbVibrant = requireViewById(R.id.scheme_vibrant);
+        RadioButton rbExpressive = requireViewById(R.id.scheme_expressive);
+        RadioButton rbNeutral = requireViewById(R.id.scheme_neutral);
+        RadioButton rbContent = requireViewById(R.id.scheme_content);
+
+        radioButtons.add(rbTonalSpot);
+        radioButtons.add(rbVibrant);
+        radioButtons.add(rbExpressive);
+        radioButtons.add(rbNeutral);
+        radioButtons.add(rbContent);
+
+        for (RadioButton rb : radioButtons) {
+            rb.setOnClickListener(v -> {
+                for (RadioButton other : radioButtons) {
+                    other.setChecked(other == v);
+                }
+                if (v.getId() == R.id.scheme_tonal_spot) {
+                    mSchemeType = "Tonal Spot";
+                } else if (v.getId() == R.id.scheme_vibrant) {
+                    mSchemeType = "Vibrant";
+                } else if (v.getId() == R.id.scheme_expressive) {
+                    mSchemeType = "Expressive";
+                } else if (v.getId() == R.id.scheme_neutral) {
+                    mSchemeType = "Neutral";
+                } else if (v.getId() == R.id.scheme_content) {
+                    mSchemeType = "Content";
+                }
+            });
+        }
+
         List<MenuItem> menuItems = new ArrayList<>();
         menuItems.add(MenuItem.builder(this)
-                .setTitle("Enable RRO")
+                .setTitle("Apply")
                 .setOnClickListener(i -> {
                     int seedColor = getSeedColor();
                     Hct seed = Hct.fromInt(seedColor);
-                    mScheme = new SchemeVibrant(seed, !mIsLightMode, 0.0);
-                    updateOverlay();
-                    updateFrameworkOverlay();
+                    boolean isDark = !mIsLightMode;
+                    switch (mSchemeType) {
+                        case "Tonal Spot": mScheme = new SchemeTonalSpot(seed, isDark, 0.0); break;
+                        case "Expressive": mScheme = new SchemeExpressive(seed, isDark, 0.0); break;
+                        case "Neutral": mScheme = new SchemeNeutral(seed, isDark, 0.0); break;
+                        case "Content": mScheme = new SchemeContent(seed, isDark, 0.0); break;
+                        default: mScheme = new SchemeVibrant(seed, isDark, 0.0); break;
+                    }
+
+                    FabricatedOverlay appOverlay = createAppOverlay();
+                    FabricatedOverlay frameworkOverlay = createFrameworkOverlay();
+
+                    OverlayManagerTransaction.Builder transaction =
+                            new OverlayManagerTransaction.Builder()
+                            .unregisterFabricatedOverlay(
+                                    new OverlayIdentifier(OWNING_PACKAGE, OVERLAY_NAME))
+                            .unregisterFabricatedOverlay(
+                                    new OverlayIdentifier(OWNING_PACKAGE, ANDROID_OVERLAY_NAME))
+                            .registerFabricatedOverlay(appOverlay)
+                            .setEnabled(appOverlay.getIdentifier(), true)
+                            .setEnabled(appOverlay.getIdentifier(), true, 0)
+                            .registerFabricatedOverlay(frameworkOverlay)
+                            .setEnabled(frameworkOverlay.getIdentifier(), true)
+                            .setEnabled(frameworkOverlay.getIdentifier(), true, 0);
+
+                    mOverlayManager.commit(transaction.build());
                 })
                 .build());
         menuItems.add(MenuItem.builder(this)
-                .setTitle("Disable RRO")
+                .setTitle("Reset")
                 .setOnClickListener(i -> {
                     disableOverlay();
                     disableFrameworkOverlay();
@@ -173,14 +263,16 @@
     private int getSeedColor() {
         float hue = (float) mSeekBar.getProgress();
 
-        // Set saturation and value to max 1.0f
-        float[] hsv = {hue, 1.0f, 1.0f};
+        float[] hsv = {hue, mSaturation, mValue};
         return Color.HSVToColor(hsv);
     }
 
     private void updateColorPreview() {
         int color = getSeedColor();
         ((GradientDrawable) mColorPreview.getBackground()).setColor(color);
+        if (mHexInput != null) {
+            mHexInput.setText(String.format("#%06X", (0xFFFFFF & color)));
+        }
     }
 
     private void disableOverlay() {
@@ -199,11 +291,10 @@
         mOverlayManager.commit(transaction.build());
     }
 
-    private void updateOverlay() {
-        disableOverlay();
+    private FabricatedOverlay createAppOverlay() {
 
-        FabricatedOverlay overlay = new FabricatedOverlay.Builder(OWNING_PACKAGE, OVERLAY_NAME,
-                TARGET_PACKAGE)
+        FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder(
+                OWNING_PACKAGE, OVERLAY_NAME, TARGET_PACKAGE)
                 .setResourceValue("com.android.oem.tokens:string/theme_overlay",
                         TypedValue.TYPE_STRING, "oem.brand.model.android.rro:style/OemThemeOverlay",
                         null)
@@ -242,10 +333,7 @@
                         TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getErrorContainer(), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_error_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnErrorContainer(), null)
-                .setResourceValue("com.android.oem.tokens:color/color_background",
-                        TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getBackground(), null)
-                .setResourceValue("com.android.oem.tokens:color/color_on_background",
-                        TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnBackground(), null)
+
                 .setResourceValue("com.android.oem.tokens:color/color_surface",
                         TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurface(), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_surface",
@@ -280,53 +368,94 @@
                         TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerHighest(), null)
                 .setResourceValue("com.android.oem.tokens:color/color_blue",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_blue_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorBlue),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_blue",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_on_blue_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnBlue),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_blue_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_blue_container_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorBlueContainer),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_blue_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_on_blue_container_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnBlueContainer),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_green",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_green_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorGreen),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_green",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_on_green_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnGreen),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_green_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_green_container_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorGreenContainer),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_green_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_on_green_container_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnGreenContainer),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_yellow",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_yellow_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorYellow),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_yellow",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_on_yellow_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnYellow),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_yellow_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_yellow_container_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorYellowContainer),
                                 mScheme.getPrimary()), null)
                 .setResourceValue("com.android.oem.tokens:color/color_on_yellow_container",
                         TypedValue.TYPE_INT_COLOR_ARGB8,
-                        Blend.harmonize(getColor(R.color.oem_color_on_yellow_container_dark),
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnYellowContainer),
                                 mScheme.getPrimary()), null)
-                .build();
+                .setResourceValue("com.android.oem.tokens:color/color_red",
+                        TypedValue.TYPE_INT_COLOR_ARGB8,
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorRed),
+                                mScheme.getPrimary()), null)
+                .setResourceValue("com.android.oem.tokens:color/color_on_red",
+                        TypedValue.TYPE_INT_COLOR_ARGB8,
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnRed),
+                                mScheme.getPrimary()), null)
+                .setResourceValue("com.android.oem.tokens:color/color_red_container",
+                        TypedValue.TYPE_INT_COLOR_ARGB8,
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorRedContainer),
+                                mScheme.getPrimary()), null)
+                .setResourceValue("com.android.oem.tokens:color/color_on_red_container",
+                        TypedValue.TYPE_INT_COLOR_ARGB8,
+                        Blend.harmonize(Token.getColor(this, R.attr.oemColorOnRedContainer),
+                                mScheme.getPrimary()), null);
+
+        // Palette tones
+        int[] tones = {100, 99, 95, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0};
+        String[] palettes = {
+                "primary", "secondary", "tertiary", "error", "neutral", "neutral_variant"};
+
+        for (String palette : palettes) {
+            TonalPalette tonalPalette;
+            switch (palette) {
+                case "primary": tonalPalette = mScheme.primaryPalette; break;
+                case "secondary": tonalPalette = mScheme.secondaryPalette; break;
+                case "tertiary": tonalPalette = mScheme.tertiaryPalette; break;
+                case "error": tonalPalette = mScheme.errorPalette; break;
+                case "neutral": tonalPalette = mScheme.neutralPalette; break;
+                case "neutral_variant": tonalPalette = mScheme.neutralVariantPalette; break;
+                default: continue;
+            }
+
+            for (int tone : tones) {
+                String resName = "color_" + palette + "_palette_" + tone;
+                builder.setResourceValue("com.android.oem.tokens:color/" + resName,
+                        TypedValue.TYPE_INT_COLOR_ARGB8, tonalPalette.tone(tone), null);
+            }
+        }
+
+        FabricatedOverlay overlay = builder.build();
 
         if (mSquareCorners) {
             overlay.setResourceValue("com.android.oem.tokens:dimen/corner_none",
@@ -345,16 +474,10 @@
                     0f, TypedValue.COMPLEX_UNIT_DIP, null);
         }
 
-        OverlayManagerTransaction.Builder transaction =
-                new OverlayManagerTransaction.Builder()
-                        .registerFabricatedOverlay(overlay)
-                        .setEnabled(overlay.getIdentifier(), true)
-                        .setEnabled(overlay.getIdentifier(), true, 0);
-
-        mOverlayManager.commit(transaction.build());
+        return overlay;
     }
 
-    private void updateFrameworkOverlay() {
+    private FabricatedOverlay createFrameworkOverlay() {
         FabricatedOverlay overlay = new FabricatedOverlay.Builder(OWNING_PACKAGE,
                 ANDROID_OVERLAY_NAME, "android")
                 .build();
@@ -372,275 +495,238 @@
         overlay.setResourceValue("android:bool/config_useRoundIcon",
                 TypedValue.TYPE_INT_BOOLEAN, isRoundCorner, null);
 
-        overlay.setResourceValue("android:color/system_primary_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getPrimary(), null);
-        overlay.setResourceValue("android:color/system_primary_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getPrimary(), null);
-        overlay.setResourceValue("android:color/system_on_primary_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnPrimary(), null);
-        overlay.setResourceValue("android:color/system_on_primary_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnPrimary(), null);
-        overlay.setResourceValue("android:color/system_primary_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getPrimaryContainer(), null);
-        overlay.setResourceValue("android:color/system_primary_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getPrimaryContainer(), null);
-        overlay.setResourceValue("android:color/system_on_primary_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnPrimaryContainer(), null);
-        overlay.setResourceValue("android:color/system_on_primary_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnPrimaryContainer(), null);
-        overlay.setResourceValue("android:color/system_secondary_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSecondary(), null);
-        overlay.setResourceValue("android:color/system_secondary_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSecondary(), null);
-        overlay.setResourceValue("android:color/system_on_secondary_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSecondary(), null);
-        overlay.setResourceValue("android:color/system_on_secondary_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSecondary(), null);
-        overlay.setResourceValue("android:color/system_secondary_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSecondaryContainer(), null);
-        overlay.setResourceValue("android:color/system_secondary_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSecondaryContainer(), null);
-        overlay.setResourceValue("android:color/system_on_secondary_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSecondaryContainer(), null);
-        overlay.setResourceValue("android:color/system_on_secondary_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSecondaryContainer(), null);
-        overlay.setResourceValue("android:color/system_tertiary_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getTertiary(), null);
-        overlay.setResourceValue("android:color/system_tertiary_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getTertiary(), null);
-        overlay.setResourceValue("android:color/system_on_tertiary_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnTertiary(), null);
-        overlay.setResourceValue("android:color/system_on_tertiary_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnTertiary(), null);
-        overlay.setResourceValue("android:color/system_tertiary_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getTertiaryContainer(), null);
-        overlay.setResourceValue("android:color/system_tertiary_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getTertiaryContainer(), null);
-        overlay.setResourceValue("android:color/system_on_tertiary_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnTertiaryContainer(), null);
-        overlay.setResourceValue("android:color/system_on_tertiary_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnTertiaryContainer(), null);
-        overlay.setResourceValue("android:color/system_error_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getError(), null);
-        overlay.setResourceValue("android:color/system_error_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getError(), null);
-        overlay.setResourceValue("android:color/system_on_error_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnError(), null);
-        overlay.setResourceValue("android:color/system_on_error_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnError(), null);
-        overlay.setResourceValue("android:color/system_error_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getErrorContainer(), null);
-        overlay.setResourceValue("android:color/system_error_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getErrorContainer(), null);
-        overlay.setResourceValue("android:color/system_on_error_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnErrorContainer(), null);
-        overlay.setResourceValue("android:color/system_on_error_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnErrorContainer(), null);
-        overlay.setResourceValue("android:color/system_surface_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurface(), null);
-        overlay.setResourceValue("android:color/system_surface_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurface(), null);
-        overlay.setResourceValue("android:color/system_on_surface_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSurface(), null);
-        overlay.setResourceValue("android:color/system_on_surface_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSurface(), null);
-        overlay.setResourceValue("android:color/system_surface_variant_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceVariant(), null);
-        overlay.setResourceValue("android:color/system_surface_variant_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceVariant(), null);
-        overlay.setResourceValue("android:color/system_on_surface_variant_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSurfaceVariant(), null);
-        overlay.setResourceValue("android:color/system_on_surface_variant_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOnSurfaceVariant(), null);
-        overlay.setResourceValue("android:color/system_inverse_surface_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getInverseSurface(), null);
-        overlay.setResourceValue("android:color/system_inverse_surface_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getInverseSurface(), null);
-        overlay.setResourceValue("android:color/system_inverse_on_surface_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getInverseOnSurface(), null);
-        overlay.setResourceValue("android:color/system_inverse_on_surface_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getInverseOnSurface(), null);
-        overlay.setResourceValue("android:color/system_outline_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOutline(), null);
-        overlay.setResourceValue("android:color/system_outline_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOutline(), null);
-        overlay.setResourceValue("android:color/system_outline_variant_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOutlineVariant(), null);
-        overlay.setResourceValue("android:color/system_outline_variant_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getOutlineVariant(), null);
-        overlay.setResourceValue("android:color/system_scrim_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getScrim(), null);
-        overlay.setResourceValue("android:color/system_scrim_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getScrim(), null);
-        overlay.setResourceValue("android:color/system_surface_dim_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceDim(), null);
-        overlay.setResourceValue("android:color/system_surface_dim_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceDim(), null);
-        overlay.setResourceValue("android:color/system_surface_bright_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceBright(), null);
-        overlay.setResourceValue("android:color/system_surface_bright_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceBright(), null);
-        overlay.setResourceValue("android:color/system_surface_container_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainer(), null);
-        overlay.setResourceValue("android:color/system_surface_container_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainer(), null);
-        overlay.setResourceValue("android:color/system_surface_container_low_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerLow(), null);
-        overlay.setResourceValue("android:color/system_surface_container_low_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerLow(), null);
-        overlay.setResourceValue("android:color/system_surface_container_lowest_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerLowest(), null);
-        overlay.setResourceValue("android:color/system_surface_container_lowest_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerLowest(), null);
-        overlay.setResourceValue("android:color/system_surface_container_high_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerHigh(), null);
-        overlay.setResourceValue("android:color/system_surface_container_high_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerHigh(), null);
-        overlay.setResourceValue("android:color/system_surface_container_highest_dark",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerHighest(), null);
-        overlay.setResourceValue("android:color/system_surface_container_highest_light",
-                TypedValue.TYPE_INT_COLOR_ARGB8, mScheme.getSurfaceContainerHighest(), null);
+        Map<String, Integer> semanticColors = new HashMap<>();
+        semanticColors.put("primary", mScheme.getPrimary());
+        semanticColors.put("on_primary", mScheme.getOnPrimary());
+        semanticColors.put("primary_container", mScheme.getPrimaryContainer());
+        semanticColors.put("on_primary_container", mScheme.getOnPrimaryContainer());
+        semanticColors.put("secondary", mScheme.getSecondary());
+        semanticColors.put("on_secondary", mScheme.getOnSecondary());
+        semanticColors.put("secondary_container", mScheme.getSecondaryContainer());
+        semanticColors.put("on_secondary_container", mScheme.getOnSecondaryContainer());
+        semanticColors.put("tertiary", mScheme.getTertiary());
+        semanticColors.put("on_tertiary", mScheme.getOnTertiary());
+        semanticColors.put("tertiary_container", mScheme.getTertiaryContainer());
+        semanticColors.put("on_tertiary_container", mScheme.getOnTertiaryContainer());
+        semanticColors.put("error", mScheme.getError());
+        semanticColors.put("on_error", mScheme.getOnError());
+        semanticColors.put("error_container", mScheme.getErrorContainer());
+        semanticColors.put("on_error_container", mScheme.getOnErrorContainer());
+        semanticColors.put("surface", mScheme.getSurface());
+        semanticColors.put("on_surface", mScheme.getOnSurface());
+        semanticColors.put("surface_variant", mScheme.getSurfaceVariant());
+        semanticColors.put("on_surface_variant", mScheme.getOnSurfaceVariant());
+        semanticColors.put("inverse_surface", mScheme.getInverseSurface());
+        semanticColors.put("inverse_on_surface", mScheme.getInverseOnSurface());
+        semanticColors.put("outline", mScheme.getOutline());
+        semanticColors.put("outline_variant", mScheme.getOutlineVariant());
+        semanticColors.put("scrim", mScheme.getScrim());
+        semanticColors.put("surface_dim", mScheme.getSurfaceDim());
+        semanticColors.put("surface_bright", mScheme.getSurfaceBright());
+        semanticColors.put("surface_container", mScheme.getSurfaceContainer());
+        semanticColors.put("surface_container_low", mScheme.getSurfaceContainerLow());
+        semanticColors.put("surface_container_lowest", mScheme.getSurfaceContainerLowest());
+        semanticColors.put("surface_container_high", mScheme.getSurfaceContainerHigh());
+        semanticColors.put("surface_container_highest", mScheme.getSurfaceContainerHighest());
 
-        OverlayManagerTransaction.Builder transaction =
-                new OverlayManagerTransaction.Builder()
-                        .registerFabricatedOverlay(overlay)
-                        .setEnabled(overlay.getIdentifier(), true)
-                        .setEnabled(overlay.getIdentifier(), true, 0);
+        for (Map.Entry<String, Integer> entry : semanticColors.entrySet()) {
+            String name = entry.getKey();
+            int color = entry.getValue();
+            overlay.setResourceValue("android:color/system_" + name + "_dark",
+                    TypedValue.TYPE_INT_COLOR_ARGB8, color, null);
+            overlay.setResourceValue("android:color/system_" + name + "_light",
+                    TypedValue.TYPE_INT_COLOR_ARGB8, color, null);
+        }
 
-        mOverlayManager.commit(transaction.build());
+        // Palette tones
+        int[] tones = {0, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
+        String[] palettes = {"accent1", "accent2", "accent3", "neutral1", "neutral2", "error"};
+
+        for (String palette : palettes) {
+            TonalPalette tonalPalette;
+            switch (palette) {
+                case "accent1": tonalPalette = mScheme.primaryPalette; break;
+                case "accent2": tonalPalette = mScheme.secondaryPalette; break;
+                case "accent3": tonalPalette = mScheme.tertiaryPalette; break;
+                case "neutral1": tonalPalette = mScheme.neutralPalette; break;
+                case "neutral2": tonalPalette = mScheme.neutralVariantPalette; break;
+                case "error": tonalPalette = mScheme.errorPalette; break;
+                default: continue;
+            }
+
+            for (int tone : tones) {
+                int toneValue = 100 - tone / 10;
+                overlay.setResourceValue("android:color/system_" + palette + "_" + tone,
+                        TypedValue.TYPE_INT_COLOR_ARGB8, tonalPalette.tone(toneValue), null);
+            }
+        }
+
+        return overlay;
     }
 
-    private List<Pair<String, Integer>> createColorList() {
-        List<Pair<String, Integer>> list = new ArrayList<>();
+    private List<TokenDemoAdapter.TokenItem> createColorList() {
+        List<TokenDemoAdapter.TokenItem> list = new ArrayList<>();
 
-        list.add(new Pair<>("colorPrimary", R.attr.oemColorPrimary));
-        list.add(new Pair<>("colorOnPrimary", R.attr.oemColorOnPrimary));
-        list.add(new Pair<>("colorPrimaryContainer",
-                R.attr.oemColorPrimaryContainer));
-        list.add(new Pair<>("colorPrimaryOnContainer",
-                R.attr.oemColorOnPrimaryContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorPrimary", R.attr.oemColorPrimary,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnPrimary", R.attr.oemColorOnPrimary,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorPrimaryContainer",
+                R.attr.oemColorPrimaryContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorPrimaryOnContainer",
+                R.attr.oemColorOnPrimaryContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorSecondary", R.attr.oemColorSecondary));
-        list.add(new Pair<>("colorOnSecondary", R.attr.oemColorOnSecondary));
-        list.add(new Pair<>("colorSecondaryContainer",
-                R.attr.oemColorSecondaryContainer));
-        list.add(new Pair<>("colorSecondaryOnContainer",
-                R.attr.oemColorOnSecondaryContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorSecondary", R.attr.oemColorSecondary,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnSecondary", R.attr.oemColorOnSecondary,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSecondaryContainer",
+                R.attr.oemColorSecondaryContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSecondaryOnContainer",
+                R.attr.oemColorOnSecondaryContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorTertiary", R.attr.oemColorTertiary));
-        list.add(new Pair<>("colorOnTertiary", R.attr.oemColorOnTertiary));
-        list.add(new Pair<>("colorTertiaryContainer",
-                R.attr.oemColorTertiaryContainer));
-        list.add(new Pair<>("colorTertiaryOnContainer",
-                R.attr.oemColorOnTertiaryContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorTertiary", R.attr.oemColorTertiary,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnTertiary", R.attr.oemColorOnTertiary,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorTertiaryContainer",
+                R.attr.oemColorTertiaryContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorTertiaryOnContainer",
+                R.attr.oemColorOnTertiaryContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorError", R.attr.oemColorError));
-        list.add(new Pair<>("colorOnError", R.attr.oemColorOnError));
-        list.add(new Pair<>("colorErrorContainer", R.attr.oemColorErrorContainer));
-        list.add(new Pair<>("colorErrorOnContainer",
-                R.attr.oemColorOnErrorContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorError", R.attr.oemColorError,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnError", R.attr.oemColorOnError,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorErrorContainer",
+                R.attr.oemColorErrorContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorErrorOnContainer",
+                R.attr.oemColorOnErrorContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorSurface", R.attr.oemColorSurface));
-        list.add(new Pair<>("colorOnSurface", R.attr.oemColorOnSurface));
-        list.add(new Pair<>("colorSurfaceVariant", R.attr.oemColorSurfaceVariant));
-        list.add(new Pair<>("colorOnSurfaceVariant",
-                R.attr.oemColorOnSurfaceVariant));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurface", R.attr.oemColorSurface,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnSurface", R.attr.oemColorOnSurface,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceVariant",
+                R.attr.oemColorSurfaceVariant, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnSurfaceVariant",
+                R.attr.oemColorOnSurfaceVariant, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorOutline", R.attr.oemColorOutline));
+        list.add(new TokenDemoAdapter.TokenItem("colorOutline", R.attr.oemColorOutline,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorSurfaceDim", R.attr.oemColorSurfaceDim));
-        list.add(new Pair<>("colorSurfaceBright", R.attr.oemColorSurfaceBright));
-        list.add(new Pair<>("colorSurfaceContainer",
-                R.attr.oemColorSurfaceContainer));
-        list.add(new Pair<>("colorSurfaceContainerLow", R.attr.oemColorSurfaceContainerLow));
-        list.add(new Pair<>("colorSurfaceContainerLowest", R.attr.oemColorSurfaceContainerLowest));
-        list.add(new Pair<>("colorSurfaceContainerHigh",
-                R.attr.oemColorSurfaceContainerHigh));
-        list.add(new Pair<>("colorSurfaceContainerHighest",
-                R.attr.oemColorSurfaceContainerHighest));
-        list.add(new Pair<>("colorShadow",
-                R.attr.oemColorShadow));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceDim", R.attr.oemColorSurfaceDim,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceBright", R.attr.oemColorSurfaceBright,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceContainer",
+                R.attr.oemColorSurfaceContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceContainerLow",
+                R.attr.oemColorSurfaceContainerLow, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceContainerLowest",
+                R.attr.oemColorSurfaceContainerLowest, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceContainerHigh",
+                R.attr.oemColorSurfaceContainerHigh, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorSurfaceContainerHighest",
+                R.attr.oemColorSurfaceContainerHighest, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorShadow",
+                R.attr.oemColorShadow, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorBlue", R.attr.oemColorBlue));
-        list.add(new Pair<>("colorOnBlue",
-                R.attr.oemColorOnBlue));
-        list.add(new Pair<>("colorBlueContainer", R.attr.oemColorBlueContainer));
-        list.add(new Pair<>("colorOnBlueContainer",
-                R.attr.oemColorOnBlueContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorBlue", R.attr.oemColorBlue,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnBlue",
+                R.attr.oemColorOnBlue, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorBlueContainer", R.attr.oemColorBlueContainer,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnBlueContainer",
+                R.attr.oemColorOnBlueContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorGreen", R.attr.oemColorGreen));
-        list.add(new Pair<>("colorOnGreen",
-                R.attr.oemColorOnGreenContainer));
-        list.add(new Pair<>("colorGreenContainer", R.attr.oemColorGreenContainer));
-        list.add(new Pair<>("colorOnGreenContainer",
-                R.attr.oemColorOnGreenContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorGreen", R.attr.oemColorGreen,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnGreen",
+                R.attr.oemColorOnGreen, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorGreenContainer",
+                R.attr.oemColorGreenContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnGreenContainer",
+                R.attr.oemColorOnGreenContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
-        list.add(new Pair<>("colorYellow", R.attr.oemColorYellow));
-        list.add(new Pair<>("colorOnYellow",
-                R.attr.oemColorOnYellow));
-        list.add(new Pair<>("colorYellowContainer", R.attr.oemColorYellowContainer));
-        list.add(new Pair<>("colorOnYellowContainer",
-                R.attr.oemColorOnYellowContainer));
+        list.add(new TokenDemoAdapter.TokenItem("colorYellow", R.attr.oemColorYellow,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnYellow",
+                R.attr.oemColorOnYellow, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorYellowContainer",
+                R.attr.oemColorYellowContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnYellowContainer",
+                R.attr.oemColorOnYellowContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+
+        list.add(new TokenDemoAdapter.TokenItem("colorRed", R.attr.oemColorRed,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnRed", R.attr.oemColorOnRed,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorRedContainer", R.attr.oemColorRedContainer,
+                TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
+        list.add(new TokenDemoAdapter.TokenItem("colorOnRedContainer",
+                R.attr.oemColorOnRedContainer, TokenDemoAdapter.VIEW_TYPE_LIST_COLOR));
 
         return list;
     }
 
-    private List<Pair<String, Integer>> createTextList() {
-        List<Pair<String, Integer>> list = new ArrayList<>();
-        list.add(new Pair<>("textAppearanceDisplayLarge",
-                R.attr.oemTextAppearanceDisplayLarge));
-        list.add(new Pair<>("textAppearanceDisplayMedium",
-                R.attr.oemTextAppearanceDisplayMedium));
-        list.add(new Pair<>("textAppearanceDisplaySmall",
-                R.attr.oemTextAppearanceDisplaySmall));
+    private List<TokenDemoAdapter.TokenItem> createTextList() {
+        List<TokenDemoAdapter.TokenItem> list = new ArrayList<>();
+        list.add(new TokenDemoAdapter.TokenItem("Display Large",
+                R.attr.oemTextAppearanceDisplayLarge, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Display Medium",
+                R.attr.oemTextAppearanceDisplayMedium, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Display Small",
+                R.attr.oemTextAppearanceDisplaySmall, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
 
-        list.add(new Pair<>("textAppearanceHeadlineLarge",
-                R.attr.oemTextAppearanceHeadlineLarge));
-        list.add(new Pair<>("textAppearanceHeadlineMedium",
-                R.attr.oemTextAppearanceHeadlineMedium));
-        list.add(new Pair<>("textAppearanceHeadlineSmall",
-                R.attr.oemTextAppearanceHeadlineSmall));
+        list.add(new TokenDemoAdapter.TokenItem("Headline Large",
+                R.attr.oemTextAppearanceHeadlineLarge, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Headline Medium",
+                R.attr.oemTextAppearanceHeadlineMedium, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Headline Small",
+                R.attr.oemTextAppearanceHeadlineSmall, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
 
-        list.add(new Pair<>("textAppearanceTitleLarge",
-                R.attr.oemTextAppearanceTitleLarge));
-        list.add(new Pair<>("textAppearanceTitleMedium",
-                R.attr.oemTextAppearanceTitleMedium));
-        list.add(new Pair<>("textAppearanceTitleSmall",
-                R.attr.oemTextAppearanceTitleSmall));
+        list.add(new TokenDemoAdapter.TokenItem("Title Large",
+                R.attr.oemTextAppearanceTitleLarge, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Title Medium",
+                R.attr.oemTextAppearanceTitleMedium, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Title Small",
+                R.attr.oemTextAppearanceTitleSmall, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
 
-        list.add(new Pair<>("textAppearanceLabelLarge",
-                R.attr.oemTextAppearanceLabelLarge));
-        list.add(new Pair<>("textAppearanceLabelMedium",
-                R.attr.oemTextAppearanceLabelMedium));
-        list.add(new Pair<>("textAppearanceLabelSmall",
-                R.attr.oemTextAppearanceLabelSmall));
+        list.add(new TokenDemoAdapter.TokenItem("Label Large",
+                R.attr.oemTextAppearanceLabelLarge, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Label Medium",
+                R.attr.oemTextAppearanceLabelMedium, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Label Small",
+                R.attr.oemTextAppearanceLabelSmall, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
 
-        list.add(new Pair<>("textAppearanceBodyLarge",
-                R.attr.oemTextAppearanceBodyLarge));
-        list.add(new Pair<>("textAppearanceBodyMedium",
-                R.attr.oemTextAppearanceBodyMedium));
-        list.add(new Pair<>("textAppearanceBodySmall",
-                R.attr.oemTextAppearanceBodySmall));
+        list.add(new TokenDemoAdapter.TokenItem("Body Large",
+                R.attr.oemTextAppearanceBodyLarge, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Body Medium",
+                R.attr.oemTextAppearanceBodyMedium, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
+        list.add(new TokenDemoAdapter.TokenItem("Body Small",
+                R.attr.oemTextAppearanceBodySmall, TokenDemoAdapter.VIEW_TYPE_LIST_TEXT));
 
         return list;
     }
 
-    private List<Pair<String, Integer>> createCornerRadiusList() {
-        List<Pair<String, Integer>> list = new ArrayList<>();
-        list.add(new Pair<>("shapeCornerNone",
-                R.attr.oemShapeCornerNone));
-        list.add(new Pair<>("shapeCornerExtraSmall",
-                R.attr.oemShapeCornerExtraSmall));
-        list.add(new Pair<>("shapeCornerSmall",
-                R.attr.oemShapeCornerSmall));
-        list.add(new Pair<>("shapeCornerMedium",
-                R.attr.oemShapeCornerMedium));
-        list.add(new Pair<>("shapeCornerLarge",
-                R.attr.oemShapeCornerLarge));
-        list.add(new Pair<>("shapeCornerExtraLarge",
-                R.attr.oemShapeCornerExtraLarge));
-        list.add(new Pair<>("shapeCornerFull",
-                R.attr.oemShapeCornerFull));
+    private List<TokenDemoAdapter.TokenItem> createCornerRadiusList() {
+        List<TokenDemoAdapter.TokenItem> list = new ArrayList<>();
+        list.add(new TokenDemoAdapter.TokenItem("Corner None",
+                R.attr.oemShapeCornerNone, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
+        list.add(new TokenDemoAdapter.TokenItem("Corner Extra Small",
+                R.attr.oemShapeCornerExtraSmall, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
+        list.add(new TokenDemoAdapter.TokenItem("Corner Small",
+                R.attr.oemShapeCornerSmall, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
+        list.add(new TokenDemoAdapter.TokenItem("Corner Medium",
+                R.attr.oemShapeCornerMedium, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
+        list.add(new TokenDemoAdapter.TokenItem("Corner Large",
+                R.attr.oemShapeCornerLarge, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
+        list.add(new TokenDemoAdapter.TokenItem("Corner Extra Large",
+                R.attr.oemShapeCornerExtraLarge, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
+        list.add(new TokenDemoAdapter.TokenItem("Corner Full",
+                R.attr.oemShapeCornerFull, TokenDemoAdapter.VIEW_TYPE_LIST_SHAPE));
 
         return list;
     }
@@ -653,6 +739,10 @@
         if (r <= 0.001f) {
             return "M 0 0 H 100 V 100 H 0 Z"; // Simple rectangle
         }
+        // Handle the fully rounded (circle) case
+        if (r >= 49.99f) {
+            return "M 50 0 A 50 50 0 1 1 50 100 A 50 50 0 1 1 50 0 Z";
+        }
         return String.format(
                 Locale.US,
                 "M %f 0 L %f 0 A %f %f 0 0 1 100 %f L 100 %f A %f %f 0 0 1 %f 100 L %f 100 A %f "
diff --git a/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenDemoAdapter.java b/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenDemoAdapter.java
index 0d6f3be..6878958 100644
--- a/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenDemoAdapter.java
+++ b/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenDemoAdapter.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.graphics.drawable.GradientDrawable;
-import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -41,9 +40,23 @@
     static final int VIEW_TYPE_LIST_TEXT = 2;
     static final int VIEW_TYPE_LIST_SHAPE = 3;
 
-    private final List<Pair<String, Integer>> mItems;
+    public static class TokenItem {
+        public final String name;
+        public final int attrId;
+        public final int type;
 
-    public TokenDemoAdapter(List<Pair<String, Integer>> items) {
+        public TokenItem(String name, int attrId, int type) {
+            this.name = name;
+            this.attrId = attrId;
+            this.type = type;
+        }
+    }
+
+    private final List<TokenItem> mItems;
+    // Cached value to avoid repeated slow reads of oemShapeCornerFull token
+    private Float mFullCornerRadius = null;
+
+    public TokenDemoAdapter(List<TokenItem> items) {
         mItems = items;
     }
 
@@ -51,36 +64,60 @@
     @Override
     public TokenDemoItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         LayoutInflater inflater = LayoutInflater.from(parent.getContext());
-        View view = inflater.inflate(R.layout.car_ui_recycler_view_list_item, parent, false);
+        View view;
+        switch (viewType) {
+            case VIEW_TYPE_LIST_COLOR:
+                view = inflater.inflate(R.layout.token_list_item_color, parent, false);
+                break;
+            case VIEW_TYPE_LIST_TEXT:
+                view = inflater.inflate(R.layout.token_list_item_text, parent, false);
+                break;
+            case VIEW_TYPE_LIST_SHAPE:
+                view = inflater.inflate(R.layout.token_list_item_shape, parent, false);
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid view type: " + viewType);
+        }
         return new TokenDemoItemViewHolder(view);
     }
 
     @Override
     public void onBindViewHolder(@NonNull TokenDemoItemViewHolder holder, int position) {
-        Pair<String, Integer> tokenInfo = mItems.get(position);
+        TokenItem item = mItems.get(position);
         Context oemContext = Token.createOemStyledContext(holder.itemView.getContext());
 
         switch (holder.getItemViewType()) {
             case VIEW_TYPE_LIST_COLOR:
-                holder.mText.setText(tokenInfo.first);
-                int color = Token.getColor(oemContext, tokenInfo.second);
-                holder.mText.setTextColor(color);
+                holder.mText.setText(item.name);
+                int color = Token.getColor(oemContext, item.attrId);
+                GradientDrawable circle = new GradientDrawable();
+                circle.setShape(GradientDrawable.RECTANGLE);
+                if (mFullCornerRadius == null) {
+                    mFullCornerRadius = Token.getCornerRadius(oemContext,
+                            R.attr.oemShapeCornerFull);
+                }
+                circle.setCornerRadius(mFullCornerRadius);
+                circle.setColor(color);
+                holder.mColorIndicator.setBackground(circle);
+                holder.mText.setTextColor(Token.getColor(oemContext, R.attr.oemColorOnSurface));
                 break;
             case VIEW_TYPE_LIST_TEXT:
-                holder.mText.setText(tokenInfo.first);
+                holder.mText.setText(item.name);
                 int textAppearanceId = Token.getTextAppearance(oemContext,
-                        tokenInfo.second);
+                        item.attrId);
                 holder.mText.setTextAppearance(textAppearanceId);
                 break;
             case VIEW_TYPE_LIST_SHAPE:
                 float cornerRadius = Token.getCornerRadius(oemContext,
-                        tokenInfo.second);
-                GradientDrawable background = new GradientDrawable();
-                background.setColor(
-                        holder.itemView.getResources().getColor(android.R.color.holo_blue_dark));
-                background.setCornerRadius(cornerRadius);
-                holder.mText.setText(tokenInfo.first);
-                holder.mText.setBackground(background);
+                        item.attrId);
+                GradientDrawable shape = new GradientDrawable();
+                shape.setShape(GradientDrawable.RECTANGLE);
+                shape.setColor(Token.getColor(oemContext, R.attr.oemColorPrimary));
+                shape.setCornerRadius(cornerRadius);
+                holder.mColorIndicator.setBackground(shape);
+
+                holder.mText.setText(item.name);
+
                 break;
             default:
                 throw new IllegalStateException("Unexpected value: " + holder.getItemViewType());
@@ -89,19 +126,10 @@
 
     @Override
     public int getItemViewType(int position) {
-        Pair<String, Integer> tokenInfo = mItems.get(position);
-        if (tokenInfo.first.contains("color")) {
-            return VIEW_TYPE_LIST_COLOR;
-        } else if (tokenInfo.first.contains("textAppearance")) {
-            return VIEW_TYPE_LIST_TEXT;
-        } else if (tokenInfo.first.contains("shapeCorner")) {
-            return VIEW_TYPE_LIST_SHAPE;
-        }
-
-        throw new IllegalStateException("Unknown view type.");
-
+        return mItems.get(position).type;
     }
 
+
     @Override
     public int getItemCount() {
         return mItems.size();
@@ -109,10 +137,12 @@
 
     public static class TokenDemoItemViewHolder extends RecyclerView.ViewHolder {
         TextView mText;
+        View mColorIndicator;
 
         TokenDemoItemViewHolder(@NonNull View itemView) {
             super(itemView);
             mText = itemView.findViewById(R.id.textTitle);
+            mColorIndicator = itemView.findViewById(R.id.color_indicator);
         }
     }
 }
diff --git a/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenProvider.java b/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenProvider.java
new file mode 100644
index 0000000..9932b6d
--- /dev/null
+++ b/car-ui-lib/aaos-studio/src/main/java/com/android/aaos/studio/TokenProvider.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2026 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.aaos.studio;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.oem.tokens.Token;
+
+import java.util.Objects;
+
+public class TokenProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    @Nullable
+    public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) {
+        if ("dumpTokens".equals(method)) {
+            Bundle bundle = new Bundle();
+            bundle.putString("tokens", Token.dump(Objects.requireNonNull(getContext())));
+            return bundle;
+        }
+        return null;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/car-ui-lib/aaos-studio/src/main/res/layout/car_ui_recycler_view_list_item.xml b/car-ui-lib/aaos-studio/src/main/res/layout/car_ui_recycler_view_list_item.xml
deleted file mode 100644
index 597ebcc..0000000
--- a/car-ui-lib/aaos-studio/src/main/res/layout/car_ui_recycler_view_list_item.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="horizontal">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="10dp"
-        android:layout_marginBottom="10dp"
-        android:id="@+id/textTitle"
-        android:text="TESTING"/>
-
-</LinearLayout>
diff --git a/car-ui-lib/aaos-studio/src/main/res/layout/token_activity.xml b/car-ui-lib/aaos-studio/src/main/res/layout/token_activity.xml
index 14004b0..dd8df0c 100644
--- a/car-ui-lib/aaos-studio/src/main/res/layout/token_activity.xml
+++ b/car-ui-lib/aaos-studio/src/main/res/layout/token_activity.xml
@@ -31,59 +31,146 @@
 
         <androidx.constraintlayout.widget.ConstraintLayout
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content">
+                android:layout_height="wrap_content"
+                android:padding="16dp">
 
             <TextView
-                android:id="@+id/primary_label"
-                android:textSize="24sp"
-                android:layout_marginBottom="50dp"
+                android:id="@+id/seed_color_label"
+                android:textAppearance="?attr/oemTextAppearanceHeadlineSmall"
+                android:textStyle="bold"
                 app:layout_constraintTop_toTopOf="parent"
                 app:layout_constraintStart_toStartOf="parent"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="Seed color"/>
+                android:text="Seed Color"/>
 
             <SeekBar
                 android:id="@+id/color_seekbar"
-                android:layout_width="320dp"
+                android:layout_width="0dp"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="8dp"
                 app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@id/primary_label"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/seed_color_label"
                 android:progressDrawable="@drawable/hue_gradient"
                 android:thumbTint="?android:attr/textColorPrimary"
                 android:splitTrack="false"
-                android:max="320"
+                android:max="360"
                 android:progress="0" />
 
+            <TextView
+                android:id="@+id/hex_code_label"
+                android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                android:layout_marginTop="16dp"
+                app:layout_constraintTop_toBottomOf="@id/color_seekbar"
+                app:layout_constraintStart_toStartOf="parent"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Hex Code"/>
+
+            <LinearLayout
+                android:id="@+id/hex_container"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="4dp"
+                android:orientation="horizontal"
+                android:gravity="center_vertical"
+                app:layout_constraintTop_toBottomOf="@id/hex_code_label"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent">
+
+                <View
+                    android:id="@+id/color_preview"
+                    android:layout_width="56dp"
+                    android:layout_height="56dp"
+                    android:background="@drawable/round_bg"/>
+
+                <EditText
+                    android:id="@+id/hex_input"
+                    android:layout_width="0dp"
+                    android:layout_height="76dp"
+                    android:layout_weight="1"
+                    android:layout_marginStart="8dp"
+                    android:fontFamily="monospace"
+                    android:text="#B5CFFF"
+                    android:textAllCaps="true"
+                    android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                    android:gravity="center_vertical"
+                    android:inputType="textCapCharacters"/>
+            </LinearLayout>
+
+            <GridLayout
+                android:id="@+id/scheme_grid"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
+                android:columnCount="2"
+                app:layout_constraintTop_toBottomOf="@id/hex_container"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent">
+
+                <RadioButton
+                    android:id="@+id/scheme_tonal_spot"
+                    android:layout_width="0dp"
+                    android:layout_columnWeight="1"
+                    android:minHeight="76dp"
+                    android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                    android:text="Tonal Spot"/>
+                <RadioButton
+                    android:id="@+id/scheme_vibrant"
+                    android:layout_width="0dp"
+                    android:layout_columnWeight="1"
+                    android:minHeight="76dp"
+                    android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                    android:text="Vibrant"
+                    android:checked="true"/>
+                <RadioButton
+                    android:id="@+id/scheme_expressive"
+                    android:layout_width="0dp"
+                    android:layout_columnWeight="1"
+                    android:minHeight="76dp"
+                    android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                    android:text="Expressive"/>
+                <RadioButton
+                    android:id="@+id/scheme_neutral"
+                    android:layout_width="0dp"
+                    android:layout_columnWeight="1"
+                    android:minHeight="76dp"
+                    android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                    android:text="Neutral"/>
+                <RadioButton
+                    android:id="@+id/scheme_content"
+                    android:layout_width="0dp"
+                    android:layout_columnWeight="1"
+                    android:minHeight="76dp"
+                    android:textAppearance="?attr/oemTextAppearanceBodyLarge"
+                    android:text="Content"/>
+            </GridLayout>
+
             <Switch
                 android:id="@+id/light_switch"
-                app:layout_constraintTop_toBottomOf="@id/color_seekbar"
+                android:layout_marginTop="16dp"
+                app:layout_constraintTop_toBottomOf="@id/scheme_grid"
                 app:layout_constraintStart_toStartOf="parent"
-                android:text="Light Mode"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1" />
+                app:layout_constraintEnd_toEndOf="parent"
+                android:text="Dark Mode"
+                android:textAppearance="?attr/oemTextAppearanceTitleLarge"
+                android:minHeight="76dp"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content" />
 
             <Switch
                 android:id="@+id/corner_switch"
+                android:layout_marginTop="8dp"
                 app:layout_constraintTop_toBottomOf="@id/light_switch"
                 app:layout_constraintStart_toStartOf="parent"
-                android:text="Squared Corners"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1" />
-
-            <View
-                android:id="@+id/color_preview"
-                app:layout_constraintTop_toTopOf="@id/primary_label"
-                app:layout_constraintBottom_toBottomOf="@id/light_switch"
                 app:layout_constraintEnd_toEndOf="parent"
-                android:layout_width="100dp"
-                android:layout_height="100dp"
-                android:background="@drawable/round_bg"/>
+                android:text="Squared Corners"
+                android:textAppearance="?attr/oemTextAppearanceTitleLarge"
+                android:minHeight="76dp"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content" />
         </androidx.constraintlayout.widget.ConstraintLayout>
-
-
     </ScrollView>
 
     <androidx.constraintlayout.widget.Guideline
diff --git a/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_color.xml b/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_color.xml
new file mode 100644
index 0000000..bcdd786
--- /dev/null
+++ b/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_color.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 The Android Open Source Project -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical">
+
+    <View
+        android:id="@+id/color_indicator"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:id="@+id/textTitle"/>
+
+</LinearLayout>
diff --git a/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_shape.xml b/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_shape.xml
new file mode 100644
index 0000000..1b9197e
--- /dev/null
+++ b/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_shape.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 The Android Open Source Project -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical">
+
+    <View
+        android:id="@+id/color_indicator"
+        android:layout_width="104dp"
+        android:layout_height="48dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:id="@+id/textTitle"/>
+
+</LinearLayout>
diff --git a/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_text.xml b/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_text.xml
new file mode 100644
index 0000000..40ad034
--- /dev/null
+++ b/car-ui-lib/aaos-studio/src/main/res/layout/token_list_item_text.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 The Android Open Source Project -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:id="@+id/textTitle"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"/>
+
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/pluginsupport/PluginFactorySingleton.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/pluginsupport/PluginFactorySingleton.java
index 4c13a60..6b702cc 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/pluginsupport/PluginFactorySingleton.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/pluginsupport/PluginFactorySingleton.java
@@ -255,6 +255,14 @@
             Log.e(TAG, "Something went wrong when invoking getPluginFactory: ", e);
             sInstance = new PluginFactoryStub();
             return;
+        } catch (IncompatibleClassChangeError e) {
+            Log.e(TAG, "Something went wrong when invoking getPluginFactory: ", e);
+            sInstance = new PluginFactoryStub();
+            return;
+        } catch (Throwable e) {
+            Log.e(TAG, "Something went wrong when invoking getPluginFactory: ", e);
+            sInstance = new PluginFactoryStub();
+            return;
         }
 
         Log.i(TAG, "Loaded plugin " + pluginPackageName
diff --git a/car-ui-lib/car-ui-lib/src/main/res-private/values/priv-release_id.xml b/car-ui-lib/car-ui-lib/src/main/res-private/values/priv-release_id.xml
index d6a7826..3144e0c 100644
--- a/car-ui-lib/car-ui-lib/src/main/res-private/values/priv-release_id.xml
+++ b/car-ui-lib/car-ui-lib/src/main/res-private/values/priv-release_id.xml
@@ -17,5 +17,5 @@
     <!-- This value should NOT be overlaid or changed by OEMs.
          It represents the approximate date when the code was pushed to AOSP.
     -->
-    <string name="com_android_car_ui_ub_release_id" translatable="false">2026-04-24</string>
+    <string name="com_android_car_ui_ub_release_id" translatable="false">2026-05-20</string>
 </resources>
diff --git a/car-ui-lib/oem-tokens/OWNERS b/car-ui-lib/oem-tokens/OWNERS
new file mode 100644
index 0000000..43a3ffa
--- /dev/null
+++ b/car-ui-lib/oem-tokens/OWNERS
@@ -0,0 +1,9 @@
+# People who can approve changes for submission.
+rlagos@google.com
+alwa@google.com
+nirajdesai@google.com
+rampara@google.com
+
+# For urgent reviews only
+stenning@google.com
+
diff --git a/car-ui-lib/oem-tokens/lib/src/main/java/com/android/car/oem/tokens/Token.java b/car-ui-lib/oem-tokens/lib/src/main/java/com/android/car/oem/tokens/Token.java
index 31f4ebe..498b923 100644
--- a/car-ui-lib/oem-tokens/lib/src/main/java/com/android/car/oem/tokens/Token.java
+++ b/car-ui-lib/oem-tokens/lib/src/main/java/com/android/car/oem/tokens/Token.java
@@ -40,6 +40,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.TreeMap;
 
 /**
  * Public interface for general CarUi static functions.
@@ -254,7 +255,12 @@
      * Return a mapping of current values for OEM Design tokens.
      */
     public static String dump(@NonNull Context context) {
-        return createTokenMap(context).toString();
+        TreeMap<String, String> map = new TreeMap<>(createTokenMap(context));
+        StringBuilder sb = new StringBuilder();
+        for (java.util.Map.Entry<String, String> entry : map.entrySet()) {
+            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("\n");
+        }
+        return sb.toString();
     }
 
     /**
diff --git a/car-ui-lib/oem-tokens/lib/src/main/res/values/colors.xml b/car-ui-lib/oem-tokens/lib/src/main/res/values/colors.xml
index 68d251c..93bd831 100644
--- a/car-ui-lib/oem-tokens/lib/src/main/res/values/colors.xml
+++ b/car-ui-lib/oem-tokens/lib/src/main/res/values/colors.xml
@@ -15,87 +15,87 @@
 -->
 <resources>
     <color name="oem_default_color_primary_palette_100">#FFFFFF</color>
-    <color name="oem_default_color_primary_palette_99">#fbfcff</color>
-    <color name="oem_default_color_primary_palette_95">#e4f3ff</color>
-    <color name="oem_default_color_primary_palette_90">#c5e7ff</color>
-    <color name="oem_default_color_primary_palette_80">#91cef5</color>
-    <color name="oem_default_color_primary_palette_70">#76b2d8</color>
-    <color name="oem_default_color_primary_palette_60">#5a98bc</color>
-    <color name="oem_default_color_primary_palette_50">#3e7ea1</color>
-    <color name="oem_default_color_primary_palette_40">#1f6587</color>
-    <color name="oem_default_color_primary_palette_30">#004c6b</color>
-    <color name="oem_default_color_primary_palette_20">#00344b</color>
-    <color name="oem_default_color_primary_palette_10">#001e2d</color>
+    <color name="oem_default_color_primary_palette_99">#FAFBFF</color>
+    <color name="oem_default_color_primary_palette_95">#ECF3FE</color>
+    <color name="oem_default_color_primary_palette_90">#D3E3FD</color>
+    <color name="oem_default_color_primary_palette_80">#A8C7FA</color>
+    <color name="oem_default_color_primary_palette_70">#7CACF8</color>
+    <color name="oem_default_color_primary_palette_60">#4C8DF6</color>
+    <color name="oem_default_color_primary_palette_50">#1B6EF3</color>
+    <color name="oem_default_color_primary_palette_40">#0B57D0</color>
+    <color name="oem_default_color_primary_palette_30">#0842A0</color>
+    <color name="oem_default_color_primary_palette_20">#062E6F</color>
+    <color name="oem_default_color_primary_palette_10">#041E49</color>
     <color name="oem_default_color_primary_palette_0">#000000</color>
 
     <color name="oem_default_color_secondary_palette_100">#FFFFFF</color>
-    <color name="oem_default_color_secondary_palette_99">#fbfcff</color>
-    <color name="oem_default_color_secondary_palette_95">#EDF0FF</color>
-    <color name="oem_default_color_secondary_palette_90">#d2e5f4</color>
-    <color name="oem_default_color_secondary_palette_80">#b6c9d8</color>
-    <color name="oem_default_color_secondary_palette_70">#9baebc</color>
-    <color name="oem_default_color_secondary_palette_60">#8093a1</color>
-    <color name="oem_default_color_secondary_palette_50">#677987</color>
-    <color name="oem_default_color_secondary_palette_40">#4f616d</color>
-    <color name="oem_default_color_secondary_palette_30">#374955</color>
-    <color name="oem_default_color_secondary_palette_20">#20333e</color>
-    <color name="oem_default_color_secondary_palette_10">#0a1e28</color>
+    <color name="oem_default_color_secondary_palette_99">#F7FCFF</color>
+    <color name="oem_default_color_secondary_palette_95">#DFF3FF</color>
+    <color name="oem_default_color_secondary_palette_90">#C2E7FF</color>
+    <color name="oem_default_color_secondary_palette_80">#7FCFFF</color>
+    <color name="oem_default_color_secondary_palette_70">#5AB3F0</color>
+    <color name="oem_default_color_secondary_palette_60">#3998D3</color>
+    <color name="oem_default_color_secondary_palette_50">#047DB7</color>
+    <color name="oem_default_color_secondary_palette_40">#00639B</color>
+    <color name="oem_default_color_secondary_palette_30">#004A77</color>
+    <color name="oem_default_color_secondary_palette_20">#003355</color>
+    <color name="oem_default_color_secondary_palette_10">#001D35</color>
     <color name="oem_default_color_secondary_palette_0">#000000</color>
 
     <color name="oem_default_color_tertiary_palette_100">#FFFFFF</color>
-    <color name="oem_default_color_tertiary_palette_99">#fbfcff</color>
-    <color name="oem_default_color_tertiary_palette_95">#f5eeff</color>
-    <color name="oem_default_color_tertiary_palette_90">#e7deff</color>
-    <color name="oem_default_color_tertiary_palette_80">#cbc1e9</color>
-    <color name="oem_default_color_tertiary_palette_70">#b0a6cd</color>
-    <color name="oem_default_color_tertiary_palette_60">#958bb1</color>
-    <color name="oem_default_color_tertiary_palette_50">#7b7296</color>
-    <color name="oem_default_color_tertiary_palette_40">#62597c</color>
-    <color name="oem_default_color_tertiary_palette_30">#4a4263</color>
-    <color name="oem_default_color_tertiary_palette_20">#332c4c</color>
-    <color name="oem_default_color_tertiary_palette_10">#1e1735</color>
+    <color name="oem_default_color_tertiary_palette_99">#F2FFEE</color>
+    <color name="oem_default_color_tertiary_palette_95">#E7F8ED</color>
+    <color name="oem_default_color_tertiary_palette_90">#C4EED0</color>
+    <color name="oem_default_color_tertiary_palette_80">#6DD58C</color>
+    <color name="oem_default_color_tertiary_palette_70">#37BE5F</color>
+    <color name="oem_default_color_tertiary_palette_60">#1EA446</color>
+    <color name="oem_default_color_tertiary_palette_50">#198639</color>
+    <color name="oem_default_color_tertiary_palette_40">#146C2E</color>
+    <color name="oem_default_color_tertiary_palette_30">#0F5223</color>
+    <color name="oem_default_color_tertiary_palette_20">#0A3818</color>
+    <color name="oem_default_color_tertiary_palette_10">#072711</color>
     <color name="oem_default_color_tertiary_palette_0">#000000</color>
 
     <color name="oem_default_color_error_palette_100">#FFFFFF</color>
     <color name="oem_default_color_error_palette_99">#FFFBFF</color>
-    <color name="oem_default_color_error_palette_95">#ffedea</color>
-    <color name="oem_default_color_error_palette_90">#ffdad5</color>
-    <color name="oem_default_color_error_palette_80">#ffb4aa</color>
-    <color name="oem_default_color_error_palette_70">#ff897c</color>
-    <color name="oem_default_color_error_palette_60">#ff5448</color>
-    <color name="oem_default_color_error_palette_50">#de372f</color>
-    <color name="oem_default_color_error_palette_40">#ba1b19</color>
-    <color name="oem_default_color_error_palette_30">#930008</color>
-    <color name="oem_default_color_error_palette_20">#690004</color>
-    <color name="oem_default_color_error_palette_10">#410001</color>
+    <color name="oem_default_color_error_palette_95">#FFEDEA</color>
+    <color name="oem_default_color_error_palette_90">#FFDAD6</color>
+    <color name="oem_default_color_error_palette_80">#FFB4AB</color>
+    <color name="oem_default_color_error_palette_70">#FF897D</color>
+    <color name="oem_default_color_error_palette_60">#FF5449</color>
+    <color name="oem_default_color_error_palette_50">#DE3730</color>
+    <color name="oem_default_color_error_palette_40">#B3261E</color>
+    <color name="oem_default_color_error_palette_30">#8C1D18</color>
+    <color name="oem_default_color_error_palette_20">#601410</color>
+    <color name="oem_default_color_error_palette_10">#410E0B</color>
     <color name="oem_default_color_error_palette_0">#000000</color>
 
     <color name="oem_default_color_neutral_palette_100">#FFFFFF</color>
-    <color name="oem_default_color_neutral_palette_99">#fbfcff</color>
-    <color name="oem_default_color_neutral_palette_95">#eef1f6</color>
-    <color name="oem_default_color_neutral_palette_90">#dfe3e7</color>
-    <color name="oem_default_color_neutral_palette_80">#c3c7cb</color>
-    <color name="oem_default_color_neutral_palette_70">#a8acb0</color>
-    <color name="oem_default_color_neutral_palette_60">#8d9195</color>
-    <color name="oem_default_color_neutral_palette_50">#73787c</color>
-    <color name="oem_default_color_neutral_palette_40">#5a5f63</color>
-    <color name="oem_default_color_neutral_palette_30">#43474b</color>
-    <color name="oem_default_color_neutral_palette_20">#2c3134</color>
-    <color name="oem_default_color_neutral_palette_10">#181c1f</color>
+    <color name="oem_default_color_neutral_palette_99">#FEFBFF</color>
+    <color name="oem_default_color_neutral_palette_95">#F1F0F7</color>
+    <color name="oem_default_color_neutral_palette_90">#E3E1E9</color>
+    <color name="oem_default_color_neutral_palette_80">#C7C6CD</color>
+    <color name="oem_default_color_neutral_palette_70">#ABAAB1</color>
+    <color name="oem_default_color_neutral_palette_60">#909097</color>
+    <color name="oem_default_color_neutral_palette_50">#77767D</color>
+    <color name="oem_default_color_neutral_palette_40">#5E5E64</color>
+    <color name="oem_default_color_neutral_palette_30">#46464C</color>
+    <color name="oem_default_color_neutral_palette_20">#2F3036</color>
+    <color name="oem_default_color_neutral_palette_10">#1A1B21</color>
     <color name="oem_default_color_neutral_palette_0">#000000</color>
 
     <color name="oem_default_color_neutral_variant_palette_100">#FFFFFF</color>
-    <color name="oem_default_color_neutral_variant_palette_99">#fbfcff</color>
-    <color name="oem_default_color_neutral_variant_palette_95">#ebf1f8</color>
-    <color name="oem_default_color_neutral_variant_palette_90">#dde3ea</color>
-    <color name="oem_default_color_neutral_variant_palette_80">#c1c7ce</color>
-    <color name="oem_default_color_neutral_variant_palette_70">#a5acb2</color>
-    <color name="oem_default_color_neutral_variant_palette_60">#8b9297</color>
-    <color name="oem_default_color_neutral_variant_palette_50">#71787e</color>
-    <color name="oem_default_color_neutral_variant_palette_40">#585f65</color>
-    <color name="oem_default_color_neutral_variant_palette_30">#41484d</color>
-    <color name="oem_default_color_neutral_variant_palette_20">#2b3136</color>
-    <color name="oem_default_color_neutral_variant_palette_10">#161c21</color>
+    <color name="oem_default_color_neutral_variant_palette_99">#FEFBFF</color>
+    <color name="oem_default_color_neutral_variant_palette_95">#F0F0FA</color>
+    <color name="oem_default_color_neutral_variant_palette_90">#E2E1EC</color>
+    <color name="oem_default_color_neutral_variant_palette_80">#C6C6D0</color>
+    <color name="oem_default_color_neutral_variant_palette_70">#AAAAB4</color>
+    <color name="oem_default_color_neutral_variant_palette_60">#90909A</color>
+    <color name="oem_default_color_neutral_variant_palette_50">#767680</color>
+    <color name="oem_default_color_neutral_variant_palette_40">#5D5E67</color>
+    <color name="oem_default_color_neutral_variant_palette_30">#45464F</color>
+    <color name="oem_default_color_neutral_variant_palette_20">#2F3038</color>
+    <color name="oem_default_color_neutral_variant_palette_10">#1A1B23</color>
     <color name="oem_default_color_neutral_variant_palette_0">#000000</color>
 
     <color name="oem_color_surface_dim">#D7DADF</color>
@@ -105,6 +105,7 @@
     <color name="oem_color_surface_container_lowest">@color/oem_default_color_neutral_palette_100</color>
     <color name="oem_color_surface_container_high">#E5E8ED</color>
     <color name="oem_color_surface_container_highest">@color/oem_default_color_neutral_palette_90</color>
+
     <color name="oem_color_blue">#0057CC</color>
     <color name="oem_color_on_blue">#FFFFFF</color>
     <color name="oem_color_blue_container">#D9E2FF</color>
diff --git a/car-ui-lib/oem-tokens/lib/src/main/res/values/styles.xml b/car-ui-lib/oem-tokens/lib/src/main/res/values/styles.xml
index ae2e456..7a50e81 100644
--- a/car-ui-lib/oem-tokens/lib/src/main/res/values/styles.xml
+++ b/car-ui-lib/oem-tokens/lib/src/main/res/values/styles.xml
@@ -155,13 +155,13 @@
         <item name="oemColorScrim">?attr/oemColorNeutralPalette10</item>
         <item name="oemColorOutlineVariant">?attr/oemColorNeutralVariantPalette90</item>
         <item name="oemColorSurfaceTint">?attr/oemColorPrimaryPalette10</item>
-        <item name="oemColorSurfaceDim">@color/oem_color_surface_dim</item>
-        <item name="oemColorSurfaceBright">@color/oem_color_surface_bright</item>
-        <item name="oemColorSurfaceContainer">@color/oem_color_surface_container</item>
-        <item name="oemColorSurfaceContainerLow">@color/oem_color_surface_container_low</item>
-        <item name="oemColorSurfaceContainerLowest">@color/oem_color_surface_container_lowest</item>
-        <item name="oemColorSurfaceContainerHigh">@color/oem_color_surface_container_high</item>
-        <item name="oemColorSurfaceContainerHighest">@color/oem_color_surface_container_highest</item>
+        <item name="oemColorSurfaceDim">?attr/oemColorNeutralPalette90</item>
+        <item name="oemColorSurfaceBright">?attr/oemColorNeutralPalette99</item>
+        <item name="oemColorSurfaceContainer">?attr/oemColorNeutralPalette95</item>
+        <item name="oemColorSurfaceContainerLow">?attr/oemColorNeutralPalette99</item>
+        <item name="oemColorSurfaceContainerLowest">?attr/oemColorNeutralPalette100</item>
+        <item name="oemColorSurfaceContainerHigh">?attr/oemColorNeutralPalette90</item>
+        <item name="oemColorSurfaceContainerHighest">?attr/oemColorNeutralPalette80</item>
         <item name="oemColorBlue">@color/oem_color_blue</item>
         <item name="oemColorOnBlue">@color/oem_color_on_blue</item>
         <item name="oemColorBlueContainer">@color/oem_color_blue_container</item>
@@ -169,7 +169,7 @@
         <item name="oemColorRed">@color/oem_color_red</item>
         <item name="oemColorOnRed">@color/oem_color_on_red</item>
         <item name="oemColorRedContainer">@color/oem_color_red_container</item>
-        <item name="oemColorOnRedContainer">@color/oem_color_on_blue_container</item>
+        <item name="oemColorOnRedContainer">@color/oem_color_on_red_container</item>
         <item name="oemColorGreen">@color/oem_color_green</item>
         <item name="oemColorOnGreen">@color/oem_color_on_green</item>
         <item name="oemColorGreenContainer">@color/oem_color_green_container</item>
@@ -205,16 +205,16 @@
         <item name="oemColorOnSurfaceInverse">?attr/oemColorNeutralVariantPalette10</item>
         <item name="oemColorPrimaryInverse">?attr/oemColorPrimaryPalette40</item>
         <item name="oemColorOutline">?attr/oemColorNeutralVariantPalette60</item>
-        <item name="oemColorScrim">?attr/oemColorNeutralPalette80</item>
+        <item name="oemColorScrim">?attr/oemColorNeutralPalette0</item>
         <item name="oemColorOutlineVariant">?attr/oemColorNeutralVariantPalette30</item>
         <item name="oemColorSurfaceTint">?attr/oemColorPrimaryPalette80</item>
-        <item name="oemColorSurfaceDim">#0F1417</item>
-        <item name="oemColorSurfaceBright">#353A3D</item>
-        <item name="oemColorSurfaceContainer">#1C2024</item>
+        <item name="oemColorSurfaceDim">?attr/oemColorNeutralPalette10</item>
+        <item name="oemColorSurfaceBright">?attr/oemColorNeutralPalette30</item>
+        <item name="oemColorSurfaceContainer">?attr/oemColorNeutralPalette10</item>
         <item name="oemColorSurfaceContainerLow">?attr/oemColorNeutralPalette10</item>
-        <item name="oemColorSurfaceContainerLowest">#0A0F12</item>
-        <item name="oemColorSurfaceContainerHigh">#262B2E</item>
-        <item name="oemColorSurfaceContainerHighest">#313539</item>
+        <item name="oemColorSurfaceContainerLowest">?attr/oemColorNeutralPalette0</item>
+        <item name="oemColorSurfaceContainerHigh">?attr/oemColorNeutralPalette20</item>
+        <item name="oemColorSurfaceContainerHighest">?attr/oemColorNeutralPalette30</item>
         <item name="oemColorBlue">@color/oem_color_blue_dark</item>
         <item name="oemColorOnBlue">@color/oem_color_on_blue_dark</item>
         <item name="oemColorBlueContainer">@color/oem_color_blue_container_dark</item>
@@ -392,7 +392,6 @@
         <item name="oemShapeCornerLarge">?com.android.oem.tokens:attr/shapeCornerLarge</item>
         <item name="oemShapeCornerExtraLarge">?com.android.oem.tokens:attr/shapeCornerExtraLarge</item>
         <item name="oemShapeCornerFull">?com.android.oem.tokens:attr/shapeCornerFull</item>
-
     </style>
 
     <style name="OemTokenSharedLibraryOverlay.Base">
@@ -507,40 +506,40 @@
     </style>
 
     <style name="OemTokenSharedLibraryOverlay.Base.Light">
-        <item name="com.android.oem.tokens:colorPrimary">?attr/com.android.oem.tokens:colorPrimaryPalette40</item>
-        <item name="com.android.oem.tokens:colorOnPrimary">?attr/com.android.oem.tokens:colorPrimaryPalette100</item>
-        <item name="com.android.oem.tokens:colorPrimaryContainer">?attr/com.android.oem.tokens:colorPrimaryPalette90</item>
-        <item name="com.android.oem.tokens:colorOnPrimaryContainer">?attr/com.android.oem.tokens:colorPrimaryPalette10</item>
-        <item name="com.android.oem.tokens:colorSecondary">?attr/com.android.oem.tokens:colorSecondaryPalette40</item>
-        <item name="com.android.oem.tokens:colorOnSecondary">?attr/com.android.oem.tokens:colorSecondaryPalette100</item>
-        <item name="com.android.oem.tokens:colorSecondaryContainer">?attr/com.android.oem.tokens:colorSecondaryPalette90</item>
-        <item name="com.android.oem.tokens:colorOnSecondaryContainer">?attr/com.android.oem.tokens:colorSecondaryPalette10</item>
-        <item name="com.android.oem.tokens:colorTertiary">?attr/com.android.oem.tokens:colorTertiaryPalette40</item>
-        <item name="com.android.oem.tokens:colorOnTertiary">?attr/com.android.oem.tokens:colorTertiaryPalette100</item>
-        <item name="com.android.oem.tokens:colorTertiaryContainer">?attr/com.android.oem.tokens:colorTertiaryPalette90</item>
-        <item name="com.android.oem.tokens:colorOnTertiaryContainer">?attr/com.android.oem.tokens:colorTertiaryPalette10</item>
-        <item name="com.android.oem.tokens:colorError">?attr/com.android.oem.tokens:colorErrorPalette40</item>
-        <item name="com.android.oem.tokens:colorOnError">?attr/com.android.oem.tokens:colorErrorPalette100</item>
-        <item name="com.android.oem.tokens:colorErrorContainer">?attr/com.android.oem.tokens:colorErrorPalette90</item>
-        <item name="com.android.oem.tokens:colorOnErrorContainer">?attr/com.android.oem.tokens:colorErrorPalette10</item>
-        <item name="com.android.oem.tokens:colorSurface">?attr/com.android.oem.tokens:colorNeutralPalette99</item>
-        <item name="com.android.oem.tokens:colorOnSurface">?attr/com.android.oem.tokens:colorNeutralPalette10</item>
-        <item name="com.android.oem.tokens:colorSurfaceVariant">?attr/com.android.oem.tokens:colorNeutralVariantPalette90</item>
-        <item name="com.android.oem.tokens:colorOnSurfaceVariant">?attr/com.android.oem.tokens:colorNeutralVariantPalette30</item>
-        <item name="com.android.oem.tokens:colorSurfaceInverse">?attr/com.android.oem.tokens:colorNeutralVariantPalette10</item>
-        <item name="com.android.oem.tokens:colorOnSurfaceInverse">?attr/com.android.oem.tokens:colorNeutralVariantPalette99</item>
-        <item name="com.android.oem.tokens:colorPrimaryInverse">?attr/com.android.oem.tokens:colorPrimaryPalette80</item>
-        <item name="com.android.oem.tokens:colorOutline">?attr/com.android.oem.tokens:colorNeutralVariantPalette50</item>
-        <item name="com.android.oem.tokens:colorScrim">?attr/com.android.oem.tokens:colorNeutralPalette10</item>
-        <item name="com.android.oem.tokens:colorOutlineVariant">?attr/com.android.oem.tokens:colorNeutralVariantPalette90</item>
-        <item name="com.android.oem.tokens:colorSurfaceTint">?attr/com.android.oem.tokens:colorPrimaryPalette10</item>
-        <item name="com.android.oem.tokens:colorSurfaceDim">@color/oem_color_surface_dim</item>
-        <item name="com.android.oem.tokens:colorSurfaceBright">@color/oem_color_surface_bright</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainer">@color/oem_color_surface_container</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerLow">@color/oem_color_surface_container_low</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerLowest">@color/oem_color_surface_container_lowest</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerHigh">@color/oem_color_surface_container_high</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerHighest">@color/oem_color_surface_container_highest</item>
+        <item name="com.android.oem.tokens:colorPrimary">?com.android.oem.tokens:attr/colorPrimaryPalette40</item>
+        <item name="com.android.oem.tokens:colorOnPrimary">?com.android.oem.tokens:attr/colorPrimaryPalette100</item>
+        <item name="com.android.oem.tokens:colorPrimaryContainer">?com.android.oem.tokens:attr/colorPrimaryPalette90</item>
+        <item name="com.android.oem.tokens:colorOnPrimaryContainer">?com.android.oem.tokens:attr/colorPrimaryPalette10</item>
+        <item name="com.android.oem.tokens:colorSecondary">?com.android.oem.tokens:attr/colorSecondaryPalette40</item>
+        <item name="com.android.oem.tokens:colorOnSecondary">?com.android.oem.tokens:attr/colorSecondaryPalette100</item>
+        <item name="com.android.oem.tokens:colorSecondaryContainer">?com.android.oem.tokens:attr/colorSecondaryPalette90</item>
+        <item name="com.android.oem.tokens:colorOnSecondaryContainer">?com.android.oem.tokens:attr/colorSecondaryPalette10</item>
+        <item name="com.android.oem.tokens:colorTertiary">?com.android.oem.tokens:attr/colorTertiaryPalette40</item>
+        <item name="com.android.oem.tokens:colorOnTertiary">?com.android.oem.tokens:attr/colorTertiaryPalette100</item>
+        <item name="com.android.oem.tokens:colorTertiaryContainer">?com.android.oem.tokens:attr/colorTertiaryPalette90</item>
+        <item name="com.android.oem.tokens:colorOnTertiaryContainer">?com.android.oem.tokens:attr/colorTertiaryPalette10</item>
+        <item name="com.android.oem.tokens:colorError">?com.android.oem.tokens:attr/colorErrorPalette40</item>
+        <item name="com.android.oem.tokens:colorOnError">?com.android.oem.tokens:attr/colorErrorPalette100</item>
+        <item name="com.android.oem.tokens:colorErrorContainer">?com.android.oem.tokens:attr/colorErrorPalette90</item>
+        <item name="com.android.oem.tokens:colorOnErrorContainer">?com.android.oem.tokens:attr/colorErrorPalette10</item>
+        <item name="com.android.oem.tokens:colorSurface">?com.android.oem.tokens:attr/colorNeutralPalette99</item>
+        <item name="com.android.oem.tokens:colorOnSurface">?com.android.oem.tokens:attr/colorNeutralPalette10</item>
+        <item name="com.android.oem.tokens:colorSurfaceVariant">?com.android.oem.tokens:attr/colorNeutralVariantPalette90</item>
+        <item name="com.android.oem.tokens:colorOnSurfaceVariant">?com.android.oem.tokens:attr/colorNeutralVariantPalette30</item>
+        <item name="com.android.oem.tokens:colorSurfaceInverse">?com.android.oem.tokens:attr/colorNeutralVariantPalette10</item>
+        <item name="com.android.oem.tokens:colorOnSurfaceInverse">?com.android.oem.tokens:attr/colorNeutralVariantPalette99</item>
+        <item name="com.android.oem.tokens:colorPrimaryInverse">?com.android.oem.tokens:attr/colorPrimaryPalette80</item>
+        <item name="com.android.oem.tokens:colorOutline">?com.android.oem.tokens:attr/colorNeutralVariantPalette50</item>
+        <item name="com.android.oem.tokens:colorScrim">?com.android.oem.tokens:attr/colorNeutralPalette10</item>
+        <item name="com.android.oem.tokens:colorOutlineVariant">?com.android.oem.tokens:attr/colorNeutralVariantPalette90</item>
+        <item name="com.android.oem.tokens:colorSurfaceTint">?com.android.oem.tokens:attr/colorPrimaryPalette10</item>
+        <item name="com.android.oem.tokens:colorSurfaceDim">?com.android.oem.tokens:attr/colorNeutralPalette90</item>
+        <item name="com.android.oem.tokens:colorSurfaceBright">?com.android.oem.tokens:attr/colorNeutralPalette99</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainer">?com.android.oem.tokens:attr/colorNeutralPalette95</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerLow">?com.android.oem.tokens:attr/colorNeutralPalette99</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerLowest">?com.android.oem.tokens:attr/colorNeutralPalette100</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerHigh">?com.android.oem.tokens:attr/colorNeutralPalette90</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerHighest">?com.android.oem.tokens:attr/colorNeutralPalette80</item>
         <item name="com.android.oem.tokens:colorBlue">@color/oem_color_blue</item>
         <item name="com.android.oem.tokens:colorOnBlue">@color/oem_color_on_blue</item>
         <item name="com.android.oem.tokens:colorBlueContainer">@color/oem_color_blue_container</item>
@@ -560,40 +559,40 @@
     </style>
 
     <style name="OemTokenSharedLibraryOverlay.Base.Dark">
-        <item name="com.android.oem.tokens:colorPrimary">?attr/com.android.oem.tokens:colorPrimaryPalette80</item>
-        <item name="com.android.oem.tokens:colorOnPrimary">?attr/com.android.oem.tokens:colorPrimaryPalette20</item>
-        <item name="com.android.oem.tokens:colorPrimaryContainer">?attr/com.android.oem.tokens:colorPrimaryPalette30</item>
-        <item name="com.android.oem.tokens:colorOnPrimaryContainer">?attr/com.android.oem.tokens:colorPrimaryPalette90</item>
-        <item name="com.android.oem.tokens:colorSecondary">?attr/com.android.oem.tokens:colorSecondaryPalette80</item>
-        <item name="com.android.oem.tokens:colorOnSecondary">?attr/com.android.oem.tokens:colorSecondaryPalette20</item>
-        <item name="com.android.oem.tokens:colorSecondaryContainer">?attr/com.android.oem.tokens:colorSecondaryPalette30</item>
-        <item name="com.android.oem.tokens:colorOnSecondaryContainer">?attr/com.android.oem.tokens:colorSecondaryPalette90</item>
-        <item name="com.android.oem.tokens:colorTertiary">?attr/com.android.oem.tokens:colorTertiaryPalette80</item>
-        <item name="com.android.oem.tokens:colorOnTertiary">?attr/com.android.oem.tokens:colorTertiaryPalette20</item>
-        <item name="com.android.oem.tokens:colorTertiaryContainer">?attr/com.android.oem.tokens:colorTertiaryPalette30</item>
-        <item name="com.android.oem.tokens:colorOnTertiaryContainer">?attr/com.android.oem.tokens:colorTertiaryPalette90</item>
-        <item name="com.android.oem.tokens:colorError">?attr/com.android.oem.tokens:colorErrorPalette80</item>
-        <item name="com.android.oem.tokens:colorOnError">?attr/com.android.oem.tokens:colorErrorPalette20</item>
-        <item name="com.android.oem.tokens:colorErrorContainer">?attr/com.android.oem.tokens:colorErrorPalette30</item>
-        <item name="com.android.oem.tokens:colorOnErrorContainer">?attr/com.android.oem.tokens:colorErrorPalette90</item>
-        <item name="com.android.oem.tokens:colorSurface">?attr/com.android.oem.tokens:colorNeutralPalette10</item>
-        <item name="com.android.oem.tokens:colorOnSurface">?attr/com.android.oem.tokens:colorNeutralPalette80</item>
-        <item name="com.android.oem.tokens:colorSurfaceVariant">?attr/com.android.oem.tokens:colorNeutralVariantPalette30</item>
-        <item name="com.android.oem.tokens:colorOnSurfaceVariant">?attr/com.android.oem.tokens:colorNeutralVariantPalette80</item>
-        <item name="com.android.oem.tokens:colorSurfaceInverse">?attr/com.android.oem.tokens:colorNeutralVariantPalette80</item>
-        <item name="com.android.oem.tokens:colorOnSurfaceInverse">?attr/com.android.oem.tokens:colorNeutralVariantPalette10</item>
-        <item name="com.android.oem.tokens:colorPrimaryInverse">?attr/com.android.oem.tokens:colorPrimaryPalette40</item>
-        <item name="com.android.oem.tokens:colorOutline">?attr/com.android.oem.tokens:colorNeutralVariantPalette60</item>
-        <item name="com.android.oem.tokens:colorScrim">?attr/com.android.oem.tokens:colorNeutralPalette80</item>
-        <item name="com.android.oem.tokens:colorOutlineVariant">?attr/com.android.oem.tokens:colorNeutralVariantPalette30</item>
-        <item name="com.android.oem.tokens:colorSurfaceTint">?attr/com.android.oem.tokens:colorPrimaryPalette80</item>
-        <item name="com.android.oem.tokens:colorSurfaceDim">#0F1417</item>
-        <item name="com.android.oem.tokens:colorSurfaceBright">#353A3D</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainer">#1C2024</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerLow">?attr/com.android.oem.tokens:colorNeutralPalette10</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerLowest">#0A0F12</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerHigh">#262B2E</item>
-        <item name="com.android.oem.tokens:colorSurfaceContainerHighest">#313539</item>
+        <item name="com.android.oem.tokens:colorPrimary">?com.android.oem.tokens:attr/colorPrimaryPalette80</item>
+        <item name="com.android.oem.tokens:colorOnPrimary">?com.android.oem.tokens:attr/colorPrimaryPalette20</item>
+        <item name="com.android.oem.tokens:colorPrimaryContainer">?com.android.oem.tokens:attr/colorPrimaryPalette30</item>
+        <item name="com.android.oem.tokens:colorOnPrimaryContainer">?com.android.oem.tokens:attr/colorPrimaryPalette90</item>
+        <item name="com.android.oem.tokens:colorSecondary">?com.android.oem.tokens:attr/colorSecondaryPalette80</item>
+        <item name="com.android.oem.tokens:colorOnSecondary">?com.android.oem.tokens:attr/colorSecondaryPalette20</item>
+        <item name="com.android.oem.tokens:colorSecondaryContainer">?com.android.oem.tokens:attr/colorSecondaryPalette30</item>
+        <item name="com.android.oem.tokens:colorOnSecondaryContainer">?com.android.oem.tokens:attr/colorSecondaryPalette90</item>
+        <item name="com.android.oem.tokens:colorTertiary">?com.android.oem.tokens:attr/colorTertiaryPalette80</item>
+        <item name="com.android.oem.tokens:colorOnTertiary">?com.android.oem.tokens:attr/colorTertiaryPalette20</item>
+        <item name="com.android.oem.tokens:colorTertiaryContainer">?com.android.oem.tokens:attr/colorTertiaryPalette30</item>
+        <item name="com.android.oem.tokens:colorOnTertiaryContainer">?com.android.oem.tokens:attr/colorTertiaryPalette90</item>
+        <item name="com.android.oem.tokens:colorError">?com.android.oem.tokens:attr/colorErrorPalette80</item>
+        <item name="com.android.oem.tokens:colorOnError">?com.android.oem.tokens:attr/colorErrorPalette20</item>
+        <item name="com.android.oem.tokens:colorErrorContainer">?com.android.oem.tokens:attr/colorErrorPalette30</item>
+        <item name="com.android.oem.tokens:colorOnErrorContainer">?com.android.oem.tokens:attr/colorErrorPalette90</item>
+        <item name="com.android.oem.tokens:colorSurface">?com.android.oem.tokens:attr/colorNeutralPalette10</item>
+        <item name="com.android.oem.tokens:colorOnSurface">?com.android.oem.tokens:attr/colorNeutralPalette80</item>
+        <item name="com.android.oem.tokens:colorSurfaceVariant">?com.android.oem.tokens:attr/colorNeutralVariantPalette30</item>
+        <item name="com.android.oem.tokens:colorOnSurfaceVariant">?com.android.oem.tokens:attr/colorNeutralVariantPalette80</item>
+        <item name="com.android.oem.tokens:colorSurfaceInverse">?com.android.oem.tokens:attr/colorNeutralVariantPalette80</item>
+        <item name="com.android.oem.tokens:colorOnSurfaceInverse">?com.android.oem.tokens:attr/colorNeutralVariantPalette10</item>
+        <item name="com.android.oem.tokens:colorPrimaryInverse">?com.android.oem.tokens:attr/colorPrimaryPalette40</item>
+        <item name="com.android.oem.tokens:colorOutline">?com.android.oem.tokens:attr/colorNeutralVariantPalette60</item>
+        <item name="com.android.oem.tokens:colorScrim">?com.android.oem.tokens:attr/colorNeutralPalette0</item>
+        <item name="com.android.oem.tokens:colorOutlineVariant">?com.android.oem.tokens:attr/colorNeutralVariantPalette30</item>
+        <item name="com.android.oem.tokens:colorSurfaceTint">?com.android.oem.tokens:attr/colorPrimaryPalette80</item>
+        <item name="com.android.oem.tokens:colorSurfaceDim">?com.android.oem.tokens:attr/colorNeutralPalette10</item>
+        <item name="com.android.oem.tokens:colorSurfaceBright">?com.android.oem.tokens:attr/colorNeutralPalette30</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainer">?com.android.oem.tokens:attr/colorNeutralPalette10</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerLow">?com.android.oem.tokens:attr/colorNeutralPalette10</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerLowest">?com.android.oem.tokens:attr/colorNeutralPalette0</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerHigh">?com.android.oem.tokens:attr/colorNeutralPalette20</item>
+        <item name="com.android.oem.tokens:colorSurfaceContainerHighest">?com.android.oem.tokens:attr/colorNeutralPalette30</item>
         <item name="com.android.oem.tokens:colorBlue">@color/oem_color_blue_dark</item>
         <item name="com.android.oem.tokens:colorOnBlue">@color/oem_color_on_blue_dark</item>
         <item name="com.android.oem.tokens:colorBlueContainer">@color/oem_color_blue_container_dark</item>
@@ -613,10 +612,10 @@
     </style>
 
     <style name="BaseTextAppearance">
-        <item name="android:textColor">?oemColorOnSurface</item>
-        <item name="android:textColorHighlight">?android:textColorHighlight</item>
-        <item name="android:textColorHint">?android:textColorHint</item>
-        <item name="android:textColorLink">?android:textColorLink</item>
+        <item name="android:textColor">?attr/oemColorOnSurface</item>
+        <item name="android:textColorHighlight">?android:attr/textColorHighlight</item>
+        <item name="android:textColorHint">?android:attr/textColorHint</item>
+        <item name="android:textColorLink">?android:attr/textColorLink</item>
         <item name="android:textSize">16sp</item>
         <item name="android:textStyle">normal</item>
     </style>
diff --git a/car-ui-lib/oem-tokens/shared-lib/src/main/res/values/styles.xml b/car-ui-lib/oem-tokens/shared-lib/src/main/res/values/styles.xml
index fc9e162..58bbade 100644
--- a/car-ui-lib/oem-tokens/shared-lib/src/main/res/values/styles.xml
+++ b/car-ui-lib/oem-tokens/shared-lib/src/main/res/values/styles.xml
@@ -67,11 +67,90 @@
   <color name="color_yellow_container">@android:color/holo_orange_dark</color>
   <color name="color_on_yellow_container">@android:color/holo_orange_dark</color>
 
+  <color name="color_primary_palette_100">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_99">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_95">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_90">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_80">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_70">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_60">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_50">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_40">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_30">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_20">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_10">@android:color/holo_orange_dark</color>
+  <color name="color_primary_palette_0">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_100">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_99">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_95">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_90">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_80">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_70">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_60">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_50">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_40">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_30">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_20">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_10">@android:color/holo_orange_dark</color>
+  <color name="color_secondary_palette_0">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_100">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_99">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_95">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_90">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_80">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_70">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_60">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_50">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_40">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_30">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_20">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_10">@android:color/holo_orange_dark</color>
+  <color name="color_tertiary_palette_0">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_100">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_99">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_95">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_90">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_80">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_70">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_60">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_50">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_40">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_30">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_20">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_10">@android:color/holo_orange_dark</color>
+  <color name="color_error_palette_0">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_100">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_99">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_95">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_90">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_80">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_70">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_60">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_50">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_40">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_30">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_20">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_10">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_palette_0">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_100">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_99">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_95">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_90">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_80">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_70">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_60">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_50">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_40">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_30">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_20">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_10">@android:color/holo_orange_dark</color>
+  <color name="color_neutral_variant_palette_0">@android:color/holo_orange_dark</color>
+
   <dimen name="corner_none">0dp</dimen>
   <dimen name="corner_extra_small">8dp</dimen>
   <dimen name="corner_small">16dp</dimen>
   <dimen name="corner_medium">24dp</dimen>
-  <dimen name="corner_large">48dp</dimen>
+  <dimen name="corner_large">32dp</dimen>
   <dimen name="corner_extra_large">48dp</dimen>
   <dimen name="corner_full">1000dp</dimen>
 
@@ -127,6 +206,85 @@
     <item name="com.android.oem.tokens:colorYellowContainer">@color/color_yellow_container</item>
     <item name="com.android.oem.tokens:colorOnYellowContainer">@color/color_on_yellow_container</item>
 
+    <item name="com.android.oem.tokens:colorPrimaryPalette100">@color/color_primary_palette_100</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette99">@color/color_primary_palette_99</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette95">@color/color_primary_palette_95</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette90">@color/color_primary_palette_90</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette80">@color/color_primary_palette_80</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette70">@color/color_primary_palette_70</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette60">@color/color_primary_palette_60</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette50">@color/color_primary_palette_50</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette40">@color/color_primary_palette_40</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette30">@color/color_primary_palette_30</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette20">@color/color_primary_palette_20</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette10">@color/color_primary_palette_10</item>
+    <item name="com.android.oem.tokens:colorPrimaryPalette0">@color/color_primary_palette_0</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette100">@color/color_secondary_palette_100</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette99">@color/color_secondary_palette_99</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette95">@color/color_secondary_palette_95</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette90">@color/color_secondary_palette_90</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette80">@color/color_secondary_palette_80</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette70">@color/color_secondary_palette_70</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette60">@color/color_secondary_palette_60</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette50">@color/color_secondary_palette_50</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette40">@color/color_secondary_palette_40</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette30">@color/color_secondary_palette_30</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette20">@color/color_secondary_palette_20</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette10">@color/color_secondary_palette_10</item>
+    <item name="com.android.oem.tokens:colorSecondaryPalette0">@color/color_secondary_palette_0</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette100">@color/color_tertiary_palette_100</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette99">@color/color_tertiary_palette_99</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette95">@color/color_tertiary_palette_95</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette90">@color/color_tertiary_palette_90</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette80">@color/color_tertiary_palette_80</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette70">@color/color_tertiary_palette_70</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette60">@color/color_tertiary_palette_60</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette50">@color/color_tertiary_palette_50</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette40">@color/color_tertiary_palette_40</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette30">@color/color_tertiary_palette_30</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette20">@color/color_tertiary_palette_20</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette10">@color/color_tertiary_palette_10</item>
+    <item name="com.android.oem.tokens:colorTertiaryPalette0">@color/color_tertiary_palette_0</item>
+    <item name="com.android.oem.tokens:colorErrorPalette100">@color/color_error_palette_100</item>
+    <item name="com.android.oem.tokens:colorErrorPalette99">@color/color_error_palette_99</item>
+    <item name="com.android.oem.tokens:colorErrorPalette95">@color/color_error_palette_95</item>
+    <item name="com.android.oem.tokens:colorErrorPalette90">@color/color_error_palette_90</item>
+    <item name="com.android.oem.tokens:colorErrorPalette80">@color/color_error_palette_80</item>
+    <item name="com.android.oem.tokens:colorErrorPalette70">@color/color_error_palette_70</item>
+    <item name="com.android.oem.tokens:colorErrorPalette60">@color/color_error_palette_60</item>
+    <item name="com.android.oem.tokens:colorErrorPalette50">@color/color_error_palette_50</item>
+    <item name="com.android.oem.tokens:colorErrorPalette40">@color/color_error_palette_40</item>
+    <item name="com.android.oem.tokens:colorErrorPalette30">@color/color_error_palette_30</item>
+    <item name="com.android.oem.tokens:colorErrorPalette20">@color/color_error_palette_20</item>
+    <item name="com.android.oem.tokens:colorErrorPalette10">@color/color_error_palette_10</item>
+    <item name="com.android.oem.tokens:colorErrorPalette0">@color/color_error_palette_0</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette100">@color/color_neutral_palette_100</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette99">@color/color_neutral_palette_99</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette95">@color/color_neutral_palette_95</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette90">@color/color_neutral_palette_90</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette80">@color/color_neutral_palette_80</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette70">@color/color_neutral_palette_70</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette60">@color/color_neutral_palette_60</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette50">@color/color_neutral_palette_50</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette40">@color/color_neutral_palette_40</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette30">@color/color_neutral_palette_30</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette20">@color/color_neutral_palette_20</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette10">@color/color_neutral_palette_10</item>
+    <item name="com.android.oem.tokens:colorNeutralPalette0">@color/color_neutral_palette_0</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette100">@color/color_neutral_variant_palette_100</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette99">@color/color_neutral_variant_palette_99</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette95">@color/color_neutral_variant_palette_95</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette90">@color/color_neutral_variant_palette_90</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette80">@color/color_neutral_variant_palette_80</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette70">@color/color_neutral_variant_palette_70</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette60">@color/color_neutral_variant_palette_60</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette50">@color/color_neutral_variant_palette_50</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette40">@color/color_neutral_variant_palette_40</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette30">@color/color_neutral_variant_palette_30</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette20">@color/color_neutral_variant_palette_20</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette10">@color/color_neutral_variant_palette_10</item>
+    <item name="com.android.oem.tokens:colorNeutralVariantPalette0">@color/color_neutral_variant_palette_0</item>
+
     <item name="com.android.oem.tokens:shapeCornerNone">@dimen/corner_small</item>
     <item name="com.android.oem.tokens:shapeCornerExtraSmall">@dimen/corner_extra_small</item>
     <item name="com.android.oem.tokens:shapeCornerSmall">@dimen/corner_small</item>